2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decalstoggle;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern float smoketex;
59 extern bool reversaltrain;
60 extern bool canattack;
62 extern float damagedealt;
64 extern float hostiletime;
66 extern bool gamestarted;
68 extern XYZ envsound[30];
69 extern float envsoundvol[30];
70 extern int numenvsounds;
71 extern float envsoundlife[30];
73 extern XYZ windvector;
75 std::vector<std::shared_ptr<Person>> Person::players;
80 , animCurrent(bounceidleanim)
81 , animTarget(bounceidleanim)
88 , howactive(typeactive)
90 , superruntoggle(false)
124 , rabbitkickenabled(false)
137 , superpermanentdamage(0)
175 , normalsupdatedelay(0)
179 , forwardkeydown(false)
180 , forwardstogglekeydown(false)
181 , rightkeydown(false)
185 , jumptogglekeydown(false)
186 , crouchkeydown(false)
187 , crouchtogglekeydown(false)
189 , drawtogglekeydown(false)
190 , throwkeydown(false)
191 , throwtogglekeydown(false)
192 , attackkeydown(false)
214 , whichdirection(false)
215 , whichdirectiondelay(0)
216 , avoidsomething(false)
226 , lefthandmorphness(0)
227 , righthandmorphness(0)
231 , targetlefthandmorphness(0)
232 , targetrighthandmorphness(0)
233 , targetheadmorphness(1)
234 , targetchestmorphness(0)
235 , targettailmorphness(0)
236 , lefthandmorphstart(0)
237 , lefthandmorphend(0)
238 , righthandmorphstart(0)
239 , righthandmorphend(0)
249 , highreversaldelay(0)
250 , lowreversaldelay(0)
299 , weaponstuckwhere(0)
312 , finalpathfindpoint(0)
313 , targetpathfindpoint(0)
314 , lastpathfindpoint(0)
315 , lastpathfindpoint2(0)
316 , lastpathfindpoint3(0)
317 , lastpathfindpoint4(0)
337 , neckspurtparticledelay(0)
341 , rabbitkickragdoll(false)
343 , tempanimation("Tempanim", lowheight, neutral)
347 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
348 setProportions(1, 1, 1, 1);
351 /* Read a person in tfile. Throws an error if it’s not valid */
352 Person::Person(FILE* tfile, int mapvers, unsigned i)
356 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
358 funpackf(tfile, "Bi", &howactive);
360 howactive = typeactive;
363 funpackf(tfile, "Bf", &scale);
368 funpackf(tfile, "Bb", &immobile);
373 funpackf(tfile, "Bf", &yaw);
378 if (num_weapons < 0 || num_weapons > 5) {
379 throw InvalidPersonException();
381 if (num_weapons > 0 && num_weapons < 5) {
382 for (int j = 0; j < num_weapons; j++) {
383 weaponids[j] = weapons.size();
385 funpackf(tfile, "Bi", &type);
386 weapons.push_back(Weapon(type, id));
389 funpackf(tfile, "Bi", &numwaypoints);
390 for (int j = 0; j < numwaypoints; j++) {
391 funpackf(tfile, "Bf", &waypoints[j].x);
392 funpackf(tfile, "Bf", &waypoints[j].y);
393 funpackf(tfile, "Bf", &waypoints[j].z);
395 funpackf(tfile, "Bi", &waypointtype[j]);
397 waypointtype[j] = wpkeepwalking;
401 funpackf(tfile, "Bi", &waypoint);
402 if (waypoint > (numwaypoints - 1)) {
406 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
407 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
408 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
409 funpackf(tfile, "Bf Bf", &power, &speedmult);
412 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
414 setProportions(1, 1, 1, 1);
417 funpackf(tfile, "Bi", &numclothes);
418 for (int k = 0; k < numclothes; k++) {
420 funpackf(tfile, "Bi", &templength);
421 for (int l = 0; l < templength; l++) {
422 funpackf(tfile, "Bb", &clothes[k][l]);
424 clothes[k][templength] = '\0';
425 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
430 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
433 scale = PersonType::types[creature].defaultScale;
437 realoldcoords = coords;
440 void Person::changeCreatureType(person_type type)
444 skeletonLoad(type == rabbittype);
445 scale = PersonType::types[creature].defaultScale;
446 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
449 void Person::skeletonLoad(bool clothes)
453 PersonType::types[creature].figureFileName,
454 PersonType::types[creature].lowFigureFileName,
455 PersonType::types[creature].clothesFileName,
456 PersonType::types[creature].modelFileNames[0],
457 PersonType::types[creature].modelFileNames[1],
458 PersonType::types[creature].modelFileNames[2],
459 PersonType::types[creature].modelFileNames[3],
460 PersonType::types[creature].modelFileNames[4],
461 PersonType::types[creature].modelFileNames[5],
462 PersonType::types[creature].modelFileNames[6],
463 PersonType::types[creature].lowModelFileName,
464 PersonType::types[creature].modelClothesFileName,
467 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
470 void Person::setProportions(float head, float body, float arms, float legs)
472 proportions[0] = head;
473 proportions[1] = body;
474 proportions[2] = arms;
475 proportions[3] = legs;
478 float Person::getProportion(int part) const
480 return proportions[part];
483 XYZ Person::getProportionXYZ(int part) const
485 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
495 * GameTick/doPlayerCollisions
497 void Person::CheckKick()
499 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
503 if (Animation::animations[victim->animTarget].height != lowheight) {
504 float damagemult = PersonType::types[creature].power * power * power;
505 XYZ relative = velocity;
507 Normalise(&relative);
511 if (!Tutorial::active) {
512 emit_sound_at(heavyimpactsound, victim->coords);
515 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
516 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
519 victim->DoDamage(100 * damagemult / victim->protectionhigh);
526 animTarget = backflipanim;
528 velocity = facing * -10;
532 resume_stream(whooshsound);
535 award_bonus(id, cannon);
536 } else if (victim->isCrouch()) {
537 animTarget = rabbitkickreversedanim;
538 animCurrent = rabbitkickreversedanim;
539 victim->animCurrent = rabbitkickreversalanim;
540 victim->animTarget = rabbitkickreversalanim;
546 victim->oldcoords = victim->coords;
547 coords = victim->coords;
548 victim->targetyaw = targetyaw;
549 victim->victim = this->shared_from_this();
556 * GameTick::doPlayerCollisions - spread fire between players
557 * GameTick::ProcessDevKeys - press f to ignite
558 * Person::DoStuff - spread fire from lit campfires and bushes
560 void Person::CatchFire()
562 XYZ flatfacing, flatvelocity;
564 for (int i = 0; i < 10; i++) {
565 howmany = fabs(Random() % (skeleton.joints.size()));
567 flatvelocity = skeleton.joints[howmany].velocity;
568 flatfacing = skeleton.joints[howmany].position * scale + coords;
570 flatvelocity = velocity;
571 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
573 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
578 emit_sound_at(firestartsound, coords);
580 emit_stream_at(stream_firesound, coords);
588 * idle animation for this creature (depending on status)
590 int Person::getIdle()
592 if (Dialog::inDialog() && (howactive == typeactive) && PersonType::types[creature].hasAnimTalkIdle()) {
593 return PersonType::types[creature].animTalkIdle;
595 if (hasvictim && (victim != this->shared_from_this())) {
596 if ((!victim->dead && victim->aitype != passivetype &&
597 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
598 victim->id < Person::players.size())) {
599 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
600 return PersonType::types[creature].animFightIdle;
602 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
603 if (weapons[weaponids[weaponactive]].getType() == knife) {
604 return knifefightidleanim;
606 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
607 return swordfightidlebothanim;
609 if (weapons[weaponids[weaponactive]].getType() == sword) {
610 return swordfightidleanim;
612 if (weapons[weaponids[weaponactive]].getType() == staff) {
613 return swordfightidleanim;
616 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
617 return fightsidestep;
621 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
624 if (howactive == typesitting) {
627 if (howactive == typesittingwall) {
630 if (howactive == typesleeping) {
633 if (howactive == typedead1) {
636 if (howactive == typedead2) {
639 if (howactive == typedead3) {
642 if (howactive == typedead4) {
645 return PersonType::types[creature].animBounceIdle;
649 * crouch animation for this creature
651 int Person::getCrouch()
653 return PersonType::types[creature].animCrouch;
657 * running animation for this creature (can be upright or all fours)
661 if (superruntoggle && (weaponactive == -1)) {
662 return PersonType::types[creature].animRunning;
664 return PersonType::types[creature].animRun;
670 int Person::getStop()
672 return PersonType::types[creature].animStop;
677 int Person::getLanding()
679 return PersonType::types[creature].animLanding;
684 int Person::getLandhard()
686 return PersonType::types[creature].animLandingHard;
692 * Person::DoAnimations
695 SolidHitBonus(int playerid)
697 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
698 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
700 award_bonus(playerid, solidhit);
705 * spawns blood effects
707 void Person::DoBlood(float howmuch, int which)
709 // FIXME: should abstract out inputs
710 static int bleedxint, bleedyint;
712 if (bloodtoggle && !Tutorial::active) {
713 if (bleeding <= 0 && spurt) {
715 for (int i = 0; i < 3; i++) {
716 // emit blood particles
719 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
720 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
721 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
722 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
725 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
726 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
727 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
728 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
731 if (Random() % 2 == 0) { // 50% chance
732 for (int i = 0; i < 3; i++) {
733 if (Random() % 2 != 0) {
734 // emit teeth particles
737 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
738 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
741 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
742 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
746 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
748 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
750 Sprite::setLastSpriteSpecial(3); // sets it to teeth
756 // FIXME: manipulating attributes
757 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
760 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) {
761 bleedxint = abs(Random() % 512);
762 bleedyint = abs(Random() % 512);
766 bleedy /= realtexdetail;
767 bleedx /= realtexdetail;
768 direction = abs(Random() % 2) * 2 - 1;
777 * spawns big blood effects and ???
778 * modifies character's skin texture
780 void Person::DoBloodBig(float howmuch, int which)
782 static int bleedxint, bleedyint, i, j;
784 if (howmuch && id == 0) {
788 if (!Tutorial::active || id == 0) {
789 if (aitype != playercontrolled && howmuch > 0) {
793 if (creature == wolftype) {
794 int i = abs(Random() % 2);
796 whichsound = snarlsound;
799 whichsound = snarl2sound;
802 if (creature == rabbittype) {
803 int i = abs(Random() % 2);
805 whichsound = rabbitpainsound;
807 if (i == 1 && howmuch >= 2) {
808 whichsound = rabbitpain1sound;
812 if (whichsound != -1) {
813 emit_sound_at(whichsound, coords);
819 if (id == 0 && howmuch > 0) {
823 if (bloodtoggle && decalstoggle && !Tutorial::active) {
824 if (bleeding <= 0 && spurt) {
826 for (int i = 0; i < 3; i++) {
827 // emit blood particles
828 // FIXME: copypaste from above
831 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
832 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
833 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
834 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
837 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
838 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
839 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
840 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
845 // weird texture manipulation code follows.
846 // looks like this is painting blood onto the character's skin texture
847 // FIXME: surely there's a better way
849 int offsetx = 0, offsety = 0;
851 offsety = Random() % 40;
852 offsetx = abs(Random() % 60);
854 if (which == 190 || which == 185) {
855 offsety = Random() % 40;
856 offsetx = abs(Random() % 100) - 20;
859 offsety = Random() % 10;
860 offsetx = Random() % 10;
863 offsety = Random() % 20;
864 offsetx = Random() % 20;
866 if (which == 220 || which == 215) {
875 for (i = 0; i < 512; i++) {
876 for (j = 0; j < 512; j++) {
877 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) {
905 if (endx > 512 - 1) {
908 if (endy > 512 - 1) {
918 startx /= realtexdetail;
919 starty /= realtexdetail;
920 endx /= realtexdetail;
921 endy /= realtexdetail;
923 int texdetailint = realtexdetail;
925 for (i = startx; i < endx; i++) {
926 for (j = starty; j < endy; j++) {
927 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) {
928 color = Random() % 85 + 170;
929 where = i * skeleton.skinsize * 3 + j * 3;
930 if (skeleton.skinText[where + 0] > color / 2) {
931 skeleton.skinText[where + 0] = color / 2;
933 skeleton.skinText[where + 1] = 0;
934 skeleton.skinText[where + 2] = 0;
938 skeleton.drawmodel.textureptr.bind();
943 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) {
944 bleedxint = abs(Random() % 512);
945 bleedyint = abs(Random() % 512);
947 bleedy = bleedxint + offsetx;
948 bleedx = bleedyint + offsety;
949 bleedy /= realtexdetail;
950 bleedx /= realtexdetail;
957 if (bleedx > skeleton.skinsize - 1) {
958 bleedx = skeleton.skinsize - 1;
960 if (bleedy > skeleton.skinsize - 1) {
961 bleedy = skeleton.skinsize - 1;
963 direction = abs(Random() % 2) * 2 - 1;
965 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
966 deathbleeding += bleeding;
967 bloodloss += bleeding * 3;
969 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
970 if (abs(Random() % 2) == 0) {
971 aitype = gethelptype;
974 aitype = attacktypecutoff;
984 * similar to DoBloodBig
986 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
990 static XYZ startpoint, endpoint, colpoint, movepoint;
991 static float rotationpoint;
993 static XYZ p1, p2, p3, p0;
996 float coordsx, coordsy;
999 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1001 if (!skeleton.free) {
1002 where = DoRotation(where, 0, -yaw, 0);
1006 startpoint.y += 100;
1011 // ray testing for a tri in the character model
1012 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1013 if (whichtri != -1) {
1014 // low level geometry math
1016 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1017 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1018 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1020 bary.x = distsq(&p0, &p1);
1021 bary.y = distsq(&p0, &p2);
1022 bary.z = distsq(&p0, &p3);
1024 total = bary.x + bary.y + bary.z;
1029 bary.x = 1 - bary.x;
1030 bary.y = 1 - bary.y;
1031 bary.z = 1 - bary.z;
1033 total = bary.x + bary.y + bary.z;
1038 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1039 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1040 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1041 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1042 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1043 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1044 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;
1045 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;
1047 if (bleeding <= 0 && spurt) {
1049 for (int i = 0; i < 3; i++) {
1050 // emit blood particles
1051 // FIXME: more copypaste code
1053 if (skeleton.free) {
1054 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1055 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1056 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1057 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1060 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1061 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1062 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1063 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1068 // texture manipulation follows
1070 int offsetx = 0, offsety = 0;
1071 offsetx = (1 + coordsy) * 512 - 291;
1072 offsety = coordsx * 512 - 437;
1079 for (i = 0; i < 512; i++) {
1080 for (j = 0; j < 512; j++) {
1081 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) {
1108 if (endx > 512 - 1) {
1111 if (endy > 512 - 1) {
1114 if (endx < startx) {
1117 if (endy < starty) {
1121 startx /= realtexdetail;
1122 starty /= realtexdetail;
1123 endx /= realtexdetail;
1124 endy /= realtexdetail;
1126 int texdetailint = realtexdetail;
1128 for (i = startx; i < endx; i++) {
1129 for (j = starty; j < endy; j++) {
1130 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) {
1131 color = Random() % 85 + 170;
1132 where = i * skeleton.skinsize * 3 + j * 3;
1133 if (skeleton.skinText[where + 0] > color / 2) {
1134 skeleton.skinText[where + 0] = color / 2;
1136 skeleton.skinText[where + 1] = 0;
1137 skeleton.skinText[where + 2] = 0;
1138 } 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) {
1139 color = Random() % 85 + 170;
1140 where = i * skeleton.skinsize * 3 + j * 3;
1141 if (skeleton.skinText[where + 0] > color / 2) {
1142 skeleton.skinText[where + 0] = color / 2;
1144 skeleton.skinText[where + 1] = 0;
1145 skeleton.skinText[where + 2] = 0;
1149 skeleton.drawmodel.textureptr.bind();
1152 bleedy = (1 + coordsy) * 512;
1153 bleedx = coordsx * 512;
1154 bleedy /= realtexdetail;
1155 bleedx /= realtexdetail;
1162 if (bleedx > skeleton.skinsize - 1) {
1163 bleedx = skeleton.skinsize - 1;
1165 if (bleedy > skeleton.skinsize - 1) {
1166 bleedy = skeleton.skinsize - 1;
1168 direction = abs(Random() % 2) * 2 - 1;
1170 if (whichtri == -1) {
1174 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1175 deathbleeding += bleeding;
1176 bloodloss += bleeding * 3;
1178 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1179 if (abs(Random() % 2) == 0) {
1180 aitype = gethelptype;
1183 aitype = attacktypecutoff;
1194 * guessing this performs a reversal
1196 void Person::Reverse()
1198 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1202 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1206 if (animTarget == sweepanim) {
1207 animTarget = sweepreversedanim;
1208 animCurrent = sweepreversedanim;
1209 victim->animCurrent = sweepreversalanim;
1210 victim->animTarget = sweepreversalanim;
1212 if (animTarget == spinkickanim) {
1213 animTarget = spinkickreversedanim;
1214 animCurrent = spinkickreversedanim;
1215 victim->animCurrent = spinkickreversalanim;
1216 victim->animTarget = spinkickreversalanim;
1218 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1219 if (animTarget == rabbittacklinganim) {
1222 victim->frameCurrent = 6;
1223 victim->frameTarget = 7;
1225 animTarget = upunchreversedanim;
1226 animCurrent = upunchreversedanim;
1227 victim->animCurrent = upunchreversalanim;
1228 victim->animTarget = upunchreversalanim;
1230 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1231 if (victim->weaponactive != -1) {
1232 victim->throwtogglekeydown = 1;
1233 XYZ tempVelocity = victim->velocity * .2;
1234 if (tempVelocity.x == 0) {
1235 tempVelocity.x = .1;
1237 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1238 victim->num_weapons--;
1239 if (victim->num_weapons) {
1240 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1241 if (victim->weaponstuck == victim->num_weapons) {
1242 victim->weaponstuck = 0;
1246 victim->weaponactive = -1;
1247 for (unsigned j = 0; j < Person::players.size(); j++) {
1248 Person::players[j]->wentforweapon = 0;
1252 animTarget = staffhitreversedanim;
1253 animCurrent = staffhitreversedanim;
1254 victim->animCurrent = staffhitreversalanim;
1255 victim->animTarget = staffhitreversalanim;
1257 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1258 if (victim->weaponactive != -1) {
1259 victim->throwtogglekeydown = 1;
1260 XYZ tempVelocity = victim->velocity * .2;
1261 if (tempVelocity.x == 0) {
1262 tempVelocity.x = .1;
1264 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1265 victim->num_weapons--;
1266 if (victim->num_weapons) {
1267 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1268 if (victim->weaponstuck == victim->num_weapons) {
1269 victim->weaponstuck = 0;
1273 victim->weaponactive = -1;
1274 for (unsigned j = 0; j < Person::players.size(); j++) {
1275 Person::players[j]->wentforweapon = 0;
1278 animTarget = staffspinhitreversedanim;
1279 animCurrent = staffspinhitreversedanim;
1280 victim->animCurrent = staffspinhitreversalanim;
1281 victim->animTarget = staffspinhitreversalanim;
1283 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1284 if (victim->weaponactive != -1) {
1285 victim->throwtogglekeydown = 1;
1286 XYZ tempVelocity = victim->velocity * .2;
1287 if (tempVelocity.x == 0) {
1288 tempVelocity.x = .1;
1290 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1291 victim->num_weapons--;
1292 if (victim->num_weapons) {
1293 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1294 if (victim->weaponstuck == victim->num_weapons) {
1295 victim->weaponstuck = 0;
1299 victim->weaponactive = -1;
1300 for (unsigned j = 0; j < Person::players.size(); j++) {
1301 Person::players[j]->wentforweapon = 0;
1304 animTarget = swordslashreversedanim;
1305 animCurrent = swordslashreversedanim;
1306 victim->animCurrent = swordslashreversalanim;
1307 victim->animTarget = swordslashreversalanim;
1309 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1310 if (victim->weaponactive != -1) {
1311 victim->throwtogglekeydown = 1;
1312 XYZ tempVelocity = victim->velocity * .2;
1313 if (tempVelocity.x == 0) {
1314 tempVelocity.x = .1;
1316 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1317 victim->num_weapons--;
1318 if (victim->num_weapons) {
1319 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1320 if (victim->weaponstuck == victim->num_weapons) {
1321 victim->weaponstuck = 0;
1325 victim->weaponactive = -1;
1326 for (unsigned j = 0; j < Person::players.size(); j++) {
1327 Person::players[j]->wentforweapon = 0;
1330 animTarget = knifeslashreversedanim;
1331 animCurrent = knifeslashreversedanim;
1332 victim->animCurrent = knifeslashreversalanim;
1333 victim->animTarget = knifeslashreversalanim;
1335 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1336 victim->targettilt2 = targettilt2;
1337 victim->frameCurrent = frameCurrent;
1338 victim->frameTarget = frameTarget;
1339 victim->target = target;
1340 victim->velocity = 0;
1341 victim->oldcoords = victim->coords;
1342 victim->coords = coords;
1343 victim->targetyaw = targetyaw;
1344 victim->yaw = targetyaw;
1345 victim->victim = this->shared_from_this();
1347 if (animTarget == winduppunchanim) {
1348 animTarget = winduppunchblockedanim;
1349 victim->animTarget = blockhighleftanim;
1350 victim->frameTarget = 1;
1351 victim->target = .5;
1352 victim->victim = this->shared_from_this();
1353 victim->targetyaw = targetyaw + 180;
1355 if (animTarget == wolfslapanim) {
1356 animTarget = winduppunchblockedanim;
1357 victim->animTarget = blockhighleftanim;
1358 victim->frameTarget = 1;
1359 victim->target = .5;
1360 victim->victim = this->shared_from_this();
1361 victim->targetyaw = targetyaw + 180;
1363 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1364 animTarget = swordslashparriedanim;
1365 parriedrecently = .4;
1366 victim->parriedrecently = 0;
1367 victim->animTarget = swordslashparryanim;
1368 victim->frameTarget = 1;
1369 victim->target = .5;
1370 victim->victim = this->shared_from_this();
1371 victim->targetyaw = targetyaw + 180;
1373 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1374 if (victim->weaponactive != -1) {
1375 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1376 if (weapons[victim->weaponids[0]].getType() == staff) {
1377 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1379 if (weapons[weaponids[0]].getType() == staff) {
1380 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1382 emit_sound_at(swordstaffsound, victim->coords);
1384 emit_sound_at(metalhitsound, victim->coords);
1388 victim->Puff(righthand);
1390 victim->frameTarget = 0;
1391 victim->animTarget = staggerbackhighanim;
1392 victim->targetyaw = targetyaw + 180;
1394 aim = DoRotation(facing, 0, 90, 0) * 21;
1396 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1397 victim->num_weapons--;
1398 if (victim->num_weapons) {
1399 victim->weaponids[0] = victim->weaponids[num_weapons];
1400 if (victim->weaponstuck == victim->num_weapons) {
1401 victim->weaponstuck = 0;
1404 victim->weaponactive = -1;
1405 for (unsigned i = 0; i < Person::players.size(); i++) {
1406 Person::players[i]->wentforweapon = 0;
1410 if (abs(Random() % 20) == 0) {
1411 if (weaponactive != -1) {
1412 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1413 if (weapons[victim->weaponids[0]].getType() == staff) {
1414 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1416 if (weapons[weaponids[0]].getType() == staff) {
1417 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1420 emit_sound_at(swordstaffsound, coords);
1422 emit_sound_at(metalhitsound, coords);
1430 animTarget = staggerbackhighanim;
1431 targetyaw = targetyaw + 180;
1433 aim = DoRotation(facing, 0, 90, 0) * 21;
1435 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1438 weaponids[0] = weaponids[num_weapons];
1439 if (weaponstuck == num_weapons) {
1444 for (unsigned i = 0; i < Person::players.size(); i++) {
1445 Person::players[i]->wentforweapon = 0;
1450 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1451 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1452 victim->animTarget = dodgebackanim;
1453 victim->frameTarget = 0;
1457 rotatetarget = coords - victim->coords;
1458 Normalise(&rotatetarget);
1459 victim->targetyaw = -asin(0 - rotatetarget.x);
1460 victim->targetyaw *= 360 / 6.28;
1461 if (rotatetarget.z < 0) {
1462 victim->targetyaw = 180 - victim->targetyaw;
1465 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1467 victim->lastattack3 = victim->lastattack2;
1468 victim->lastattack2 = victim->lastattack;
1469 victim->lastattack = victim->animTarget;
1471 victim->animTarget = sweepanim;
1472 victim->frameTarget = 0;
1476 rotatetarget = coords - victim->coords;
1477 Normalise(&rotatetarget);
1478 victim->targetyaw = -asin(0 - rotatetarget.x);
1479 victim->targetyaw *= 360 / 6.28;
1480 if (rotatetarget.z < 0) {
1481 victim->targetyaw = 180 - victim->targetyaw;
1484 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1486 victim->lastattack3 = victim->lastattack2;
1487 victim->lastattack2 = victim->lastattack;
1488 victim->lastattack = victim->animTarget;
1494 victim->velocity = 0;
1496 if (aitype != playercontrolled) {
1498 if (escapednum < 2) {
1499 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1500 if ((Random() % chances) == 0) {
1506 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1514 void Person::DoDamage(float howmuch)
1518 damagetaken += howmuch / power;
1520 damagedealt += howmuch / power;
1524 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1529 if (!Tutorial::active) {
1530 damage += howmuch / power;
1531 permanentdamage += howmuch / 2 / power;
1532 superpermanentdamage += howmuch / 4 / power;
1535 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1538 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1543 camerashake += howmuch / 100;
1544 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1545 blackout = damage / damagetolerance;
1553 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1554 aitype = attacktypecutoff;
1556 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1557 if (abs(Random() % 2) == 0) {
1558 aitype = gethelptype;
1561 aitype = attacktypecutoff;
1566 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1569 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1570 if (skeleton.free) {
1571 flatvelocity2 = skeleton.joints[i].velocity;
1572 flatfacing2 = skeleton.joints[i].position * scale + coords;
1574 flatvelocity2 = velocity;
1575 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1577 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1578 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1579 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1580 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1581 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1582 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1585 emit_sound_at(splattersound, coords);
1590 if (!dead && creature == wolftype) {
1591 award_bonus(0, Wolfbonus);
1598 if (!Tutorial::active || id == 0) {
1599 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1600 int whichsound = -1;
1602 if (creature == wolftype) {
1603 int i = abs(Random() % 2);
1605 whichsound = snarlsound;
1608 whichsound = snarl2sound;
1611 if (creature == rabbittype) {
1612 int i = abs(Random() % 2);
1614 whichsound = rabbitpainsound;
1616 if (i == 1 && damage > damagetolerance) {
1617 whichsound = rabbitpain1sound;
1621 if (whichsound != -1) {
1622 emit_sound_at(whichsound, coords);
1623 addEnvSound(coords);
1631 * calculate/animate head facing direction?
1633 void Person::DoHead()
1635 static XYZ rotatearound;
1637 static float lookspeed = 500;
1639 if (!freeze && !winfreeze) {
1642 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1643 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1645 while (targetheadyaw > 180) {
1646 targetheadyaw -= 360;
1648 while (targetheadyaw < -180) {
1649 targetheadyaw += 360;
1652 if (targetheadyaw > 160) {
1653 targetheadpitch = targetheadpitch * -1;
1655 if (targetheadyaw < -160) {
1656 targetheadpitch = targetheadpitch * -1;
1658 if (targetheadyaw > 160) {
1659 targetheadyaw = targetheadyaw - 180;
1661 if (targetheadyaw < -160) {
1662 targetheadyaw = targetheadyaw + 180;
1665 if (targetheadpitch > 120) {
1666 targetheadpitch = 120;
1668 if (targetheadpitch < -120) {
1669 targetheadpitch = -120;
1671 if (targetheadyaw > 120) {
1672 targetheadyaw = 120;
1674 if (targetheadyaw < -120) {
1675 targetheadyaw = -120;
1679 targetheadpitch = 0;
1682 if (targetheadyaw > 80) {
1685 if (targetheadyaw < -80) {
1686 targetheadyaw = -80;
1688 if (targetheadpitch > 50) {
1689 targetheadpitch = 50;
1691 if (targetheadpitch < -50) {
1692 targetheadpitch = -50;
1696 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1697 headyaw = targetheadyaw;
1698 } else if (headyaw > targetheadyaw) {
1699 headyaw -= multiplier * lookspeed;
1700 } else if (headyaw < targetheadyaw) {
1701 headyaw += multiplier * lookspeed;
1704 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1705 headpitch = targetheadpitch;
1706 } else if (headpitch > targetheadpitch) {
1707 headpitch -= multiplier * lookspeed / 2;
1708 } else if (headpitch < targetheadpitch) {
1709 headpitch += multiplier * lookspeed / 2;
1712 rotatearound = jointPos(neck);
1713 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1717 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1718 facing = DoRotation(facing, headpitch * .4, 0, 0);
1719 facing = DoRotation(facing, 0, headyaw * .4, 0);
1722 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1723 facing = DoRotation(facing, headpitch * .8, 0, 0);
1724 facing = DoRotation(facing, 0, headyaw * .8, 0);
1727 if (animTarget == walkanim) {
1728 facing = DoRotation(facing, headpitch * .6, 0, 0);
1729 facing = DoRotation(facing, 0, headyaw * .6, 0);
1732 skeleton.specialforward[0] = facing;
1733 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1734 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1735 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1736 skeleton.FindRotationMuscle(i, animTarget);
1743 * ragdolls character?
1745 void Person::RagDoll(bool checkcollision)
1750 if (!skeleton.free) {
1754 if (id == 0 && isFlip()) {
1762 facing = DoRotation(facing, 0, yaw, 0);
1764 skeleton.freetime = 0;
1766 skeleton.longdead = 0;
1769 skeleton.broken = 0;
1770 skeleton.spinny = 1;
1772 skeleton.freefall = 1;
1774 if (!isnormal(velocity.x)) {
1777 if (!isnormal(velocity.y)) {
1780 if (!isnormal(velocity.z)) {
1783 if (!isnormal(yaw)) {
1786 if (!isnormal(coords.x)) {
1789 if (!isnormal(tilt)) {
1792 if (!isnormal(tilt2)) {
1796 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1797 skeleton.joints[i].delay = 0;
1798 skeleton.joints[i].locked = 0;
1799 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1800 if (!isnormal(skeleton.joints[i].position.x)) {
1801 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1803 if (!isnormal(skeleton.joints[i].position.x)) {
1804 skeleton.joints[i].position = coords;
1806 skeleton.joints[i].position.y += .1;
1807 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1808 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1811 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1812 skeleton.joints[i].velocity = 0;
1813 skeleton.joints[i].velchange = 0;
1815 skeleton.DoConstraints(&coords, &scale);
1816 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1817 skeleton.DoConstraints(&coords, &scale);
1818 skeleton.DoConstraints(&coords, &scale);
1819 skeleton.DoConstraints(&coords, &scale);
1820 skeleton.DoConstraints(&coords, &scale);
1823 speed = targetFrame().speed * 2;
1824 if (currentFrame().speed > targetFrame().speed) {
1825 speed = currentFrame().speed * 2;
1828 speed = transspeed * 2;
1833 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1834 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
1835 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);
1837 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1839 change.x = (float)(Random() % 100) / 100;
1840 change.y = (float)(Random() % 100) / 100;
1841 change.z = (float)(Random() % 100) / 100;
1842 skeleton.joints[i].velocity += change;
1843 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1845 change.x = (float)(Random() % 100) / 100;
1846 change.y = (float)(Random() % 100) / 100;
1847 change.z = (float)(Random() % 100) / 100;
1848 skeleton.joints[i].velchange += change;
1849 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1852 if (checkcollision) {
1855 if (!skeleton.joints.empty()) {
1858 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1859 average += skeleton.joints[j].position;
1861 average /= skeleton.joints.size();
1862 coords += average * scale;
1863 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1864 skeleton.joints[j].position -= average;
1868 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1869 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1870 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1871 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1874 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1875 coords.x = lowpoint.x;
1876 coords.z = lowpoint.z;
1885 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1886 velocity += skeleton.joints[i].velocity * scale;
1888 velocity /= skeleton.joints.size();
1891 if (Random() % 2 == 0) {
1892 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1893 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1894 weapons[weaponids[0]].velocity.x += .01;
1897 weaponids[0] = weaponids[num_weapons];
1898 if (weaponstuck == num_weapons) {
1903 for (unsigned i = 0; i < Person::players.size(); i++) {
1904 Person::players[i]->wentforweapon = 0;
1909 animTarget = bounceidleanim;
1910 animCurrent = bounceidleanim;
1918 void Person::FootLand(bodypart whichfoot, float opacity)
1920 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1921 cerr << "FootLand called on wrong bodypart" << endl;
1924 static XYZ terrainlight;
1925 static XYZ footvel, footpoint;
1926 if (opacity >= 1 || skiddelay <= 0) {
1929 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1930 if (distsq(&footpoint, &viewer)) {
1931 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1933 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1934 footvel = velocity / 5;
1935 if (footvel.y < .8) {
1938 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1939 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1940 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1941 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1942 if (environment == snowyenvironment) {
1943 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1945 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1947 } else if (environment == grassyenvironment) {
1948 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1949 } else if (environment == desertenvironment) {
1950 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1952 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1956 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1957 footvel = velocity / 5;
1958 if (footvel.y < .8) {
1961 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1962 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1963 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1970 * make a puff effect at a body part (dust effect?)
1972 void Person::Puff(int whichlabel)
1974 static XYZ footvel, footpoint;
1977 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1978 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1982 * I think I added this in an attempt to clean up code
1984 void Person::setTargetAnimation(int animation)
1986 animTarget = animation;
1995 void Person::DoAnimations()
1997 if (!skeleton.free) {
1998 static float oldtarget;
2000 if (isIdle() && animCurrent != getIdle()) {
2001 normalsupdatedelay = 0;
2004 if (animTarget == tempanim || animCurrent == tempanim) {
2005 Animation::animations[tempanim] = tempanimation;
2007 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2014 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2015 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2017 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2020 if (!crouchkeydown && velocity.y >= -15) {
2024 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2029 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2031 if (normaldotproduct(targfacing, velocity) >= -.3) {
2032 animTarget = flipanim;
2034 animTarget = backflipanim;
2036 crouchtogglekeydown = 1;
2045 if (Animation::animations[animTarget].attack != reversed) {
2048 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2049 crouchtogglekeydown = 0;
2050 if (aitype == playercontrolled) {
2054 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2058 crouchtogglekeydown = 1;
2062 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2064 normalsupdatedelay = 0;
2069 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2071 emit_sound_at(fireendsound, coords);
2072 pause_sound(stream_firesound);
2076 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2077 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2080 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2081 if (normaldotproduct(victim->facing, facing) > 0) {
2082 victim->animTarget = rabbittackledbackanim;
2084 victim->animTarget = rabbittackledfrontanim;
2086 victim->frameTarget = 2;
2089 victim->targetyaw = yaw;
2090 if (victim->aitype == gethelptype) {
2091 victim->DoDamage(victim->damagetolerance - victim->damage);
2093 if (PersonType::types[creature].hasClaws) {
2095 emit_sound_at(clawslicesound, victim->coords);
2097 victim->DoBloodBig(1 / victim->armorhead, 210);
2099 award_bonus(id, TackleBonus,
2100 victim->aitype == gethelptype ? 50 : 0);
2104 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2105 if (weapons[weaponids[0]].getType() == knife) {
2106 if (weaponactive == -1) {
2108 } else if (weaponactive == 0) {
2112 if (weaponactive == -1) {
2113 emit_sound_at(knifesheathesound, coords);
2115 if (weaponactive != -1) {
2116 emit_sound_at(knifedrawsound, coords, 128);
2119 drawtogglekeydown = 1;
2122 if (!Tutorial::active || id == 0) {
2123 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2124 int whichsound = -1;
2126 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2127 if (targetFrame().label == 1) {
2128 whichsound = footstepsound;
2130 whichsound = footstepsound2;
2132 if (targetFrame().label == 1) {
2133 FootLand(leftfoot, 1);
2135 if (targetFrame().label == 2) {
2136 FootLand(rightfoot, 1);
2138 if (targetFrame().label == 3 && isRun()) {
2139 FootLand(rightfoot, 1);
2140 FootLand(leftfoot, 1);
2143 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2144 if (targetFrame().label == 1) {
2145 whichsound = footstepsound3;
2147 whichsound = footstepsound4;
2152 if (targetFrame().label == 1) {
2153 whichsound = footstepsound3;
2155 whichsound = footstepsound4;
2158 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2159 if (Animation::animations[animTarget].attack != neutral) {
2160 unsigned r = abs(Random() % 3);
2162 whichsound = lowwhooshsound;
2165 whichsound = midwhooshsound;
2168 whichsound = highwhooshsound;
2171 if (Animation::animations[animTarget].attack == neutral) {
2172 whichsound = movewhooshsound;
2174 } else if (targetFrame().label == 4) {
2175 whichsound = knifeswishsound;
2177 if (targetFrame().label == 8 && !Tutorial::active) {
2178 whichsound = landsound2;
2181 if (whichsound != -1) {
2182 emit_sound_at(whichsound, coords, 256.);
2185 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2186 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2187 addEnvSound(coords, 15);
2189 addEnvSound(coords, 6);
2194 if (targetFrame().label == 3) {
2196 emit_sound_at(whichsound, coords, 128.);
2203 if (!Tutorial::active || id == 0) {
2204 if (speechdelay <= 0) {
2205 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2206 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2207 int whichsound = -1;
2208 if (targetFrame().label == 4 && aitype != playercontrolled) {
2209 if (Animation::animations[animTarget].attack != neutral) {
2210 unsigned r = abs(Random() % 4);
2211 whichsound = PersonType::types[creature].soundsAttack[r];
2216 if (whichsound != -1) {
2217 emit_sound_at(whichsound, coords);
2224 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2225 FootLand(leftfoot, 1);
2226 FootLand(rightfoot, 1);
2230 currentoffset = targetoffset;
2231 frameTarget = frameCurrent;
2232 animCurrent = animTarget;
2235 if (animCurrent == removeknifeanim && currentFrame().label == 5) {
2236 for (unsigned i = 0; i < weapons.size(); i++) {
2237 if (weapons[i].owner == -1) {
2238 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2239 if (distsq(&coords, &weapons[i].position) >= 1) {
2240 if (weapons[i].getType() != staff) {
2241 emit_sound_at(knifedrawsound, coords, 128.);
2251 if (animCurrent == crouchremoveknifeanim && currentFrame().label == 5) {
2252 for (unsigned i = 0; i < weapons.size(); i++) {
2253 bool willwork = true;
2254 if (weapons[i].owner != -1) {
2255 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2256 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2257 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2263 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2264 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2265 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2266 bool fleshstuck = false;
2267 if (weapons[i].owner != -1) {
2268 if (victim->weaponstuck != -1) {
2269 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2275 emit_sound_at(fleshstabremovesound, coords, 128.);
2277 if (weapons[i].getType() != staff) {
2278 emit_sound_at(knifedrawsound, coords, 128.);
2281 if (weapons[i].owner != -1) {
2282 victim = Person::players[weapons[i].owner];
2283 if (victim->num_weapons == 1) {
2284 victim->num_weapons = 0;
2286 victim->num_weapons = 1;
2289 //victim->weaponactive=-1;
2290 victim->skeleton.longdead = 0;
2291 victim->skeleton.free = 1;
2292 victim->skeleton.broken = 0;
2294 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2295 victim->skeleton.joints[j].velchange = 0;
2296 victim->skeleton.joints[j].locked = 0;
2302 Normalise(&relative);
2303 XYZ footvel, footpoint;
2305 footpoint = weapons[i].position;
2306 if (victim->weaponstuck != -1) {
2307 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2309 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2311 weapons[i].bloody = 2;
2312 weapons[i].blooddrip = 5;
2313 victim->weaponstuck = -1;
2316 if (victim->num_weapons > 0) {
2317 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2318 victim->weaponstuck = 0;
2320 if (victim->weaponids[0] == int(i)) {
2321 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2325 victim->jointVel(abdomen) += relative * 6;
2326 victim->jointVel(neck) += relative * 6;
2327 victim->jointVel(rightshoulder) += relative * 6;
2328 victim->jointVel(leftshoulder) += relative * 6;
2337 if (animCurrent == drawleftanim && currentFrame().label == 5) {
2338 if (weaponactive == -1) {
2340 } else if (weaponactive == 0) {
2342 if (num_weapons == 2) {
2344 buffer = weaponids[0];
2345 weaponids[0] = weaponids[1];
2346 weaponids[1] = buffer;
2349 if (weaponactive == -1) {
2350 emit_sound_at(knifesheathesound, coords, 128.);
2352 if (weaponactive != -1) {
2353 emit_sound_at(knifedrawsound, coords, 128.);
2357 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2358 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2359 Normalise(&rotatetarget);
2360 targetyaw = -asin(0 - rotatetarget.x);
2361 targetyaw *= 360 / 6.28;
2362 if (rotatetarget.z < 0) {
2363 targetyaw = 180 - targetyaw;
2366 if (animTarget == walljumprightkickanim) {
2369 if (animTarget == walljumpleftkickanim) {
2376 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2380 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2388 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2389 animTarget = rabbittackleanim;
2391 emit_sound_at(jumpsound, coords);
2399 targetloc = velocity;
2400 Normalise(&targetloc);
2401 targetloc += coords;
2402 for (unsigned i = 0; i < Person::players.size(); i++) {
2404 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2405 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2410 if (closestid != -1) {
2411 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2413 victim = Person::players[closestid];
2414 coords = victim->coords;
2415 animCurrent = rabbittacklinganim;
2416 animTarget = rabbittacklinganim;
2420 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2421 rotatetarget = coords - victim->coords;
2422 Normalise(&rotatetarget);
2423 targetyaw = -asin(0 - rotatetarget.x);
2424 targetyaw *= 360 / 6.28;
2425 if (rotatetarget.z < 0) {
2426 targetyaw = 180 - targetyaw;
2429 if (animTarget != rabbitrunninganim) {
2430 emit_sound_at(jumpsound, coords, 128.);
2437 float damagemult = PersonType::types[creature].power * power;
2439 damagemult /= victim->damagetolerance / 200;
2441 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)) {
2442 if (animCurrent == spinkickanim && currentFrame().label == 5) {
2443 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2448 if (Random() % 2 || PersonType::types[creature].hasClaws) {
2451 if (PersonType::types[creature].hasClaws) {
2455 if (!Tutorial::active) {
2456 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2458 if (PersonType::types[creature].hasClaws) {
2459 emit_sound_at(clawslicesound, victim->coords, 128.);
2461 victim->DoBloodBig(2 / victim->armorhead, 175);
2465 relative = victim->coords - coords;
2467 Normalise(&relative);
2468 relative = DoRotation(relative, 0, -90, 0);
2469 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2470 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2472 victim->jointVel(head) += relative * damagemult * 200;
2474 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2480 if (animCurrent == wolfslapanim && currentFrame().label == 5) {
2481 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2486 if (Random() % 2 || PersonType::types[creature].hasClaws) {
2488 if (PersonType::types[creature].hasClaws) {
2492 emit_sound_at(whooshhitsound, victim->coords);
2493 if (PersonType::types[creature].hasClaws) {
2494 emit_sound_at(clawslicesound, victim->coords, 128.);
2496 victim->DoBloodBig(2, 175);
2500 relative = victim->coords - coords;
2502 Normalise(&relative);
2504 Normalise(&relative);
2505 relative = DoRotation(relative, 0, 90, 0);
2506 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2507 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2509 victim->jointVel(head) += relative * damagemult * 100;
2511 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2515 if (animCurrent == walljumprightkickanim && currentFrame().label == 5) {
2516 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2523 if (!Tutorial::active) {
2524 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2526 if (PersonType::types[creature].hasClaws) {
2527 emit_sound_at(clawslicesound, victim->coords, 128.);
2529 victim->DoBloodBig(2 / victim->armorhead, 175);
2535 Normalise(&relative);
2536 relative = DoRotation(relative, 0, -90, 0);
2537 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2538 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2540 victim->jointVel(head) += relative * damagemult * 200;
2542 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2544 if (victim->damage > victim->damagetolerance) {
2545 award_bonus(id, style);
2552 if (animCurrent == walljumpleftkickanim && currentFrame().label == 5) {
2553 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2560 if (!Tutorial::active) {
2561 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2563 if (PersonType::types[creature].hasClaws) {
2564 emit_sound_at(clawslicesound, victim->coords, 128.);
2566 victim->DoBloodBig(2 / victim->armorhead, 175);
2572 Normalise(&relative);
2573 relative = DoRotation(relative, 0, 90, 0);
2574 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2575 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2577 victim->jointVel(head) += relative * damagemult * 200;
2579 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2581 if (victim->damage > victim->damagetolerance) {
2582 award_bonus(id, style);
2589 if (animCurrent == blockhighleftstrikeanim && currentFrame().label == 5) {
2590 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2599 emit_sound_at(whooshhitsound, victim->coords);
2602 relative = victim->coords - coords;
2604 Normalise(&relative);
2605 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2606 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2608 victim->jointVel(head) += relative * damagemult * 100;
2610 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2614 if (animCurrent == killanim && currentFrame().label == 8) {
2615 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2620 emit_sound_at(whooshhitsound, victim->coords, 128.);
2622 victim->skeleton.longdead = 0;
2623 victim->skeleton.free = 1;
2624 victim->skeleton.broken = 0;
2625 victim->skeleton.spinny = 1;
2627 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2628 victim->skeleton.joints[i].velchange = 0;
2629 victim->skeleton.joints[i].delay = 0;
2630 victim->skeleton.joints[i].locked = 0;
2631 //victim->skeleton.joints[i].velocity=0;
2637 Normalise(&relative);
2638 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2639 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2640 victim->skeleton.joints[i].position.y += relative.y * .3;
2641 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2642 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2644 victim->Puff(abdomen);
2645 victim->jointVel(abdomen).y = relative.y * 400;
2649 if (animCurrent == killanim && currentFrame().label == 5) {
2650 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2655 if (!Tutorial::active) {
2656 emit_sound_at(heavyimpactsound, coords, 128.);
2659 relative = victim->coords - coords;
2661 Normalise(&relative);
2662 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2663 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2665 victim->Puff(abdomen);
2666 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2670 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2671 victim->jointVel(abdomen) += relative * damagemult * 300;
2675 if (animCurrent == dropkickanim && currentFrame().label == 7) {
2676 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2681 if (!Tutorial::active) {
2682 emit_sound_at(thudsound, coords);
2685 victim->skeleton.longdead = 0;
2686 victim->skeleton.free = 1;
2687 victim->skeleton.broken = 0;
2688 victim->skeleton.spinny = 1;
2690 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2691 victim->skeleton.joints[i].velchange = 0;
2692 //victim->skeleton.joints[i].delay=0;
2693 victim->skeleton.joints[i].locked = 0;
2696 relative = victim->coords - coords;
2697 Normalise(&relative);
2699 Normalise(&relative);
2700 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2701 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2703 if (!victim->dead) {
2707 victim->Puff(abdomen);
2708 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2709 victim->jointVel(abdomen) += relative * damagemult * 200;
2711 if (!victim->dead) {
2717 if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 5) {
2720 if (!victim->skeleton.free) {
2726 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2727 emit_sound_at(knifesheathesound, coords, 128.);
2730 if (victim && hasvictim) {
2731 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2733 XYZ where, startpoint, endpoint, movepoint, colpoint;
2734 float rotationpoint;
2736 if (weapons[weaponids[weaponactive]].getType() == knife) {
2737 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2738 where -= victim->coords;
2739 if (!victim->skeleton.free) {
2740 where = DoRotation(where, 0, -victim->yaw, 0);
2744 startpoint.y += 100;
2748 if (weapons[weaponids[weaponactive]].getType() == sword) {
2749 where = weapons[weaponids[weaponactive]].position;
2750 where -= victim->coords;
2751 if (!victim->skeleton.free) {
2752 where = DoRotation(where, 0, -victim->yaw, 0);
2755 where = weapons[weaponids[weaponactive]].tippoint;
2756 where -= victim->coords;
2757 if (!victim->skeleton.free) {
2758 where = DoRotation(where, 0, -victim->yaw, 0);
2762 if (weapons[weaponids[weaponactive]].getType() == staff) {
2763 where = weapons[weaponids[weaponactive]].position;
2764 where -= victim->coords;
2765 if (!victim->skeleton.free) {
2766 where = DoRotation(where, 0, -victim->yaw, 0);
2769 where = weapons[weaponids[weaponactive]].tippoint;
2770 where -= victim->coords;
2771 if (!victim->skeleton.free) {
2772 where = DoRotation(where, 0, -victim->yaw, 0);
2778 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2780 if (whichtri != -1) {
2781 if (victim->dead != 2) {
2782 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2783 if (!victim->dead) {
2784 award_bonus(id, FinishedBonus);
2788 weapons[weaponids[weaponactive]].bloody = 2;
2791 victim->skeleton.longdead = 0;
2792 victim->skeleton.free = 1;
2793 victim->skeleton.broken = 0;
2795 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2796 victim->skeleton.joints[i].velchange = 0;
2797 victim->skeleton.joints[i].locked = 0;
2798 //victim->skeleton.joints[i].velocity=0;
2800 emit_sound_at(fleshstabsound, coords, 128);
2802 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2803 weapons[weaponids[weaponactive]].blooddrip += 5;
2804 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2806 if (whichtri == -1) {
2808 emit_sound_at(knifesheathesound, coords, 128.);
2814 if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 6) {
2816 emit_sound_at(knifedrawsound, coords, 128);
2819 if (victim && hasvictim) {
2820 XYZ footvel, footpoint;
2822 emit_sound_at(fleshstabremovesound, coords, 128.);
2825 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2827 if (weapons[weaponids[weaponactive]].getType() == sword) {
2828 XYZ where, startpoint, endpoint, movepoint;
2829 float rotationpoint;
2832 where = weapons[weaponids[weaponactive]].position;
2833 where -= victim->coords;
2834 if (!victim->skeleton.free) {
2835 where = DoRotation(where, 0, -victim->yaw, 0);
2838 where = weapons[weaponids[weaponactive]].tippoint;
2839 where -= victim->coords;
2840 if (!victim->skeleton.free) {
2841 where = DoRotation(where, 0, -victim->yaw, 0);
2847 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2848 footpoint += victim->coords;
2850 if (whichtri == -1) {
2851 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2854 if (weapons[weaponids[weaponactive]].getType() == staff) {
2855 XYZ where, startpoint, endpoint, movepoint;
2856 float rotationpoint;
2859 where = weapons[weaponids[weaponactive]].position;
2860 where -= victim->coords;
2861 if (!victim->skeleton.free) {
2862 where = DoRotation(where, 0, -victim->yaw, 0);
2865 where = weapons[weaponids[weaponactive]].tippoint;
2866 where -= victim->coords;
2867 if (!victim->skeleton.free) {
2868 where = DoRotation(where, 0, -victim->yaw, 0);
2874 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2875 footpoint += victim->coords;
2877 if (whichtri == -1) {
2878 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2881 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2883 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2884 victim->skeleton.longdead = 0;
2885 victim->skeleton.free = 1;
2886 victim->skeleton.broken = 0;
2888 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2889 victim->skeleton.joints[i].velchange = 0;
2890 victim->skeleton.joints[i].locked = 0;
2891 //victim->skeleton.joints[i].velocity=0;
2897 Normalise(&relative);
2898 //victim->Puff(abdomen);
2900 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2903 if (victim->bloodloss < victim->damagetolerance) {
2904 victim->bloodloss += 1000;
2908 victim->jointVel(abdomen) += relative * damagemult * 20;
2912 if (!hasvictim && onterrain) {
2913 weapons[weaponids[weaponactive]].bloody = 0;
2914 weapons[weaponids[weaponactive]].blooddrip = 0;
2918 if (animCurrent == upunchanim && currentFrame().label == 5) {
2919 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2928 if (!Tutorial::active) {
2929 emit_sound_at(heavyimpactsound, victim->coords, 128);
2934 relative = victim->coords - coords;
2936 Normalise(&relative);
2937 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2938 victim->skeleton.joints[i].velocity = relative * 30;
2940 victim->jointVel(head) += relative * damagemult * 150;
2942 victim->frameTarget = 0;
2943 victim->animTarget = staggerbackhardanim;
2944 victim->targetyaw = targetyaw + 180;
2946 victim->stunned = 1;
2949 victim->Puff(abdomen);
2950 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2956 if (animCurrent == winduppunchanim && currentFrame().label == 5) {
2957 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2962 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2963 if (!Tutorial::active) {
2964 emit_sound_at(thudsound, victim->coords);
2966 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2967 if (!Tutorial::active) {
2968 emit_sound_at(whooshhitsound, victim->coords);
2971 if (!Tutorial::active) {
2972 emit_sound_at(heavyimpactsound, victim->coords);
2976 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
2980 relative = victim->coords - coords;
2982 Normalise(&relative);
2984 Normalise(&relative);
2985 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2986 victim->skeleton.joints[i].velocity = relative * 5;
2988 victim->jointVel(abdomen) += relative * damagemult * 400;
2990 victim->frameTarget = 0;
2991 victim->animTarget = staggerbackhardanim;
2992 victim->targetyaw = targetyaw + 180;
2994 victim->stunned = 1;
2996 victim->Puff(abdomen);
2997 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3003 if (animCurrent == blockhighleftanim && currentFrame().label == 5) {
3004 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3005 if (victim->id == 0) {
3008 emit_sound_at(landsound2, victim->coords);
3014 if (animCurrent == swordslashparryanim && currentFrame().label == 5) {
3015 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3016 if (victim->id == 0) {
3020 if (weaponactive != -1) {
3021 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3022 if (weapons[victim->weaponids[0]].getType() == staff) {
3023 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3025 if (weapons[weaponids[0]].getType() == staff) {
3026 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3029 emit_sound_at(swordstaffsound, victim->coords);
3031 emit_sound_at(metalhitsound, victim->coords);
3039 if (animCurrent == knifethrowanim && currentFrame().label == 5) {
3040 if (weaponactive != -1) {
3043 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);
3045 weapons[weaponids[0]].thrown(aim * 50);
3048 weaponids[0] = weaponids[num_weapons];
3054 if (animCurrent == knifeslashstartanim && currentFrame().label == 5) {
3056 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3058 if (!Tutorial::active) {
3059 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3062 award_bonus(id, Slicebonus);
3063 if (!Tutorial::active) {
3064 emit_sound_at(knifeslicesound, victim->coords);
3066 //victim->jointVel(abdomen)+=relative*damagemult*200;
3067 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3068 if (victim->id != 0 || difficulty == 2) {
3069 victim->frameTarget = 0;
3070 victim->animTarget = staggerbackhardanim;
3071 victim->targetyaw = targetyaw + 180;
3075 victim->lowreversaldelay = 0;
3076 victim->highreversaldelay = 0;
3077 if (aitype != playercontrolled) {
3078 weaponmissdelay = .6;
3081 if (!Tutorial::active) {
3082 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3083 weapons[weaponids[weaponactive]].bloody = 1;
3085 weapons[weaponids[weaponactive]].blooddrip += 3;
3088 XYZ footvel, footpoint;
3090 if (skeleton.free) {
3091 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3093 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3095 if (Tutorial::active) {
3096 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3099 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3101 footvel = DoRotation(facing, 0, 90, 0) * .8;
3102 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3103 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3104 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3105 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3107 victim->DoDamage(damagemult * 0);
3111 if (animCurrent == swordslashanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3112 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3113 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3114 award_bonus(id, Slashbonus);
3116 if (!Tutorial::active) {
3117 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3118 victim->DoBloodBig(2 / victim->armorhigh, 190);
3120 victim->DoBloodBig(2 / victim->armorhigh, 185);
3122 victim->deathbleeding = 1;
3123 emit_sound_at(swordslicesound, victim->coords);
3124 victim->frameTarget = 0;
3125 victim->animTarget = staggerbackhardanim;
3126 victim->targetyaw = targetyaw + 180;
3128 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3129 weapons[weaponids[weaponactive]].bloody = 1;
3131 weapons[weaponids[weaponactive]].blooddrip += 3;
3133 float bloodlossamount;
3134 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3135 victim->bloodloss += bloodlossamount / victim->armorhigh;
3136 victim->DoDamage(damagemult * 0);
3138 XYZ footvel, footpoint;
3140 if (skeleton.free) {
3141 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3143 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3146 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3148 footvel = DoRotation(facing, 0, 90, 0) * .8;
3150 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3151 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3152 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3153 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3156 if (victim->weaponactive != -1) {
3157 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3158 if (weapons[victim->weaponids[0]].getType() == staff) {
3159 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3161 if (weapons[weaponids[0]].getType() == staff) {
3162 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3165 emit_sound_at(swordstaffsound, victim->coords);
3167 emit_sound_at(metalhitsound, victim->coords);
3172 victim->Puff(righthand);
3174 victim->frameTarget = 0;
3175 victim->animTarget = staggerbackhighanim;
3176 victim->targetyaw = targetyaw + 180;
3178 aim = DoRotation(facing, 0, 90, 0) * 21;
3180 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3181 victim->num_weapons--;
3182 if (victim->num_weapons) {
3183 victim->weaponids[0] = victim->weaponids[num_weapons];
3184 if (victim->weaponstuck == victim->num_weapons) {
3185 victim->weaponstuck = 0;
3188 victim->weaponactive = -1;
3189 for (unsigned i = 0; i < Person::players.size(); i++) {
3190 Person::players[i]->wentforweapon = 0;
3196 if (animCurrent == staffhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3197 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3198 if (!Tutorial::active) {
3199 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3204 if (Random() % 2 || PersonType::types[creature].hasClaws) {
3207 emit_sound_at(staffheadsound, victim->coords);
3211 relative = victim->coords - coords;
3213 Normalise(&relative);
3214 relative = DoRotation(relative, 0, 90, 0);
3216 Normalise(&relative);
3217 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3218 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3220 victim->jointVel(head) += relative * damagemult * 230;
3221 victim->jointVel(neck) += relative * damagemult * 230;
3223 if (!Tutorial::active) {
3224 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3226 award_bonus(id, solidhit, 30);
3231 if (animCurrent == staffspinhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3232 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3233 if (!Tutorial::active) {
3234 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3239 if (Random() % 2 || PersonType::types[creature].hasClaws) {
3242 emit_sound_at(staffheadsound, victim->coords);
3246 relative = victim->coords - coords;
3248 Normalise(&relative);
3249 relative = DoRotation(relative, 0, -90, 0);
3250 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3251 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3253 victim->jointVel(head) += relative * damagemult * 220;
3254 victim->jointVel(neck) += relative * damagemult * 220;
3256 if (!Tutorial::active) {
3257 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3259 award_bonus(id, solidhit, 60);
3264 if (animCurrent == staffgroundsmashanim && currentFrame().label == 5) {
3265 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3267 if (!Tutorial::active) {
3268 if (!victim->dead) {
3269 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3274 if (Random() % 2 || PersonType::types[creature].hasClaws) {
3277 emit_sound_at(staffbodysound, victim->coords);
3279 victim->skeleton.longdead = 0;
3280 victim->skeleton.free = 1;
3281 victim->skeleton.broken = 0;
3283 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3284 victim->skeleton.joints[i].velchange = 0;
3285 victim->skeleton.joints[i].locked = 0;
3286 //victim->skeleton.joints[i].velocity=0;
3293 Normalise(&relative);
3294 if (!victim->dead) {
3295 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3296 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3298 victim->jointVel(abdomen) += relative * damagemult * 40;
3301 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3302 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3305 victim->Puff(abdomen);
3306 if (!Tutorial::active) {
3307 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3309 if (!victim->dead) {
3310 award_bonus(id, solidhit, 40);
3316 if (animCurrent == lowkickanim && currentFrame().label == 5) {
3317 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3323 relative = victim->coords - coords;
3325 Normalise(&relative);
3329 if (Animation::animations[victim->animTarget].height == lowheight) {
3335 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3336 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3338 victim->jointVel(head) += relative * damagemult * 200;
3339 if (!Tutorial::active) {
3340 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3343 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3344 if (victim->howactive == typesleeping) {
3345 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3347 if (PersonType::types[creature].hasClaws) {
3348 emit_sound_at(clawslicesound, victim->coords, 128.);
3350 victim->DoBloodBig(2 / victim->armorhead, 175);
3353 if (victim->damage >= victim->damagetolerance) {
3356 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3357 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3359 victim->jointVel(abdomen) += relative * damagemult * 200;
3360 victim->frameTarget = 0;
3361 victim->animTarget = staggerbackhighanim;
3362 victim->targetyaw = targetyaw + 180;
3364 if (!Tutorial::active) {
3365 emit_sound_at(landsound2, victim->coords, 128.);
3367 victim->Puff(abdomen);
3368 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3369 if (PersonType::types[creature].hasClaws) {
3370 emit_sound_at(clawslicesound, victim->coords, 128.);
3372 victim->DoBloodBig(2 / victim->armorhigh, 170);
3378 if (animCurrent == sweepanim && currentFrame().label == 5) {
3379 if ((victim->animTarget != jumpupanim) &&
3380 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3381 (victim != this->shared_from_this())) {
3386 if (!Tutorial::active) {
3387 emit_sound_at(landsound2, victim->coords, 128.);
3390 relative = victim->coords - coords;
3392 Normalise(&relative);
3394 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3397 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3398 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3400 relative = DoRotation(relative, 0, -90, 0);
3402 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3403 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) {
3404 victim->skeleton.joints[i].velocity = relative * 80;
3407 victim->Puff(rightankle);
3408 victim->Puff(leftankle);
3409 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3411 if (victim->damage >= victim->damagetolerance) {
3414 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3415 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3417 relative = DoRotation(relative, 0, -90, 0);
3418 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3419 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) {
3420 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3423 victim->jointVel(abdomen) += relative * damagemult * 200;
3424 victim->frameTarget = 0;
3425 victim->animTarget = staggerbackhighanim;
3426 victim->targetyaw = targetyaw + 180;
3428 if (!Tutorial::active) {
3429 emit_sound_at(landsound2, victim->coords, 128.);
3431 victim->Puff(abdomen);
3432 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3439 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3440 if (animCurrent == spinkickreversalanim && currentFrame().label == 7) {
3449 if (!Tutorial::active) {
3450 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3452 if (PersonType::types[creature].hasClaws) {
3453 emit_sound_at(clawslicesound, victim->coords, 128);
3455 victim->DoBloodBig(2 / victim->armorhigh, 170);
3459 relative = victim->coords - oldcoords;
3461 Normalise(&relative);
3462 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3463 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3465 victim->jointVel(abdomen) += relative * damagemult * 200;
3466 victim->Puff(abdomen);
3467 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3469 award_bonus(id, Reversal);
3472 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3473 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3474 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3475 takeWeapon(victim->weaponids[victim->weaponactive]);
3476 victim->num_weapons--;
3477 if (victim->num_weapons > 0) {
3478 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3480 victim->weaponactive = -1;
3485 if (animCurrent == staffhitreversalanim && currentFrame().label == 5) {
3494 emit_sound_at(whooshhitsound, victim->coords, 128.);
3497 relative = victim->coords - oldcoords;
3499 Normalise(&relative);
3500 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3501 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3503 victim->jointVel(abdomen) += relative * damagemult * 200;
3505 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3508 if (animCurrent == staffspinhitreversalanim && currentFrame().label == 7) {
3518 award_bonus(id, staffreversebonus);
3520 if (!Tutorial::active) {
3521 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3524 award_bonus(id, staffreversebonus); // Huh, again?
3527 relative = victim->coords - oldcoords;
3529 Normalise(&relative);
3530 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3531 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3533 victim->jointVel(abdomen) += relative * damagemult * 200;
3535 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3538 if (animCurrent == upunchreversalanim && currentFrame().label == 7) {
3544 Normalise(&relative);
3546 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3547 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3549 victim->jointVel(lefthand) *= .1;
3550 victim->jointVel(leftwrist) *= .2;
3551 victim->jointVel(leftelbow) *= .5;
3552 victim->jointVel(leftshoulder) *= .7;
3553 victim->jointVel(righthand) *= .1;
3554 victim->jointVel(rightwrist) *= .2;
3555 victim->jointVel(rightelbow) *= .5;
3556 victim->jointVel(rightshoulder) *= .7;
3558 victim->Puff(abdomen);
3559 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3561 award_bonus(id, Reversal);
3564 if (weaponactive == -1) {
3565 doslice = PersonType::types[creature].hasClaws;
3567 doslice = (weapons[weaponids[0]].getType() != staff);
3570 if (weaponactive == -1) {
3571 emit_sound_at(clawslicesound, victim->coords, 128.);
3573 victim->DoBloodBig(2 / victim->armorhigh, 175);
3575 victim->DoBloodBig(2 / victim->armorhigh, 225);
3576 emit_sound_at(knifeslicesound, victim->coords);
3577 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3578 weapons[weaponids[weaponactive]].bloody = 1;
3580 weapons[weaponids[weaponactive]].blooddrip += 3;
3585 if (animCurrent == swordslashreversalanim && currentFrame().label == 7) {
3591 Normalise(&relative);
3593 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3594 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3596 victim->jointVel(lefthand) *= .1 - 1;
3597 victim->jointVel(leftwrist) *= .2 - 1;
3598 victim->jointVel(leftelbow) *= .5 - 1;
3599 victim->jointVel(leftshoulder) *= .7 - 1;
3600 victim->jointVel(righthand) *= .1 - 1;
3601 victim->jointVel(rightwrist) *= .2 - 1;
3602 victim->jointVel(rightelbow) *= .5 - 1;
3603 victim->jointVel(rightshoulder) *= .7 - 1;
3605 award_bonus(id, swordreversebonus);
3608 if (hasvictim && animCurrent == knifeslashreversalanim && currentFrame().label == 7) {
3617 if (!Tutorial::active) {
3618 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3622 relative = victim->coords - oldcoords;
3624 Normalise(&relative);
3625 relative = DoRotation(relative, 0, -90, 0);
3626 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3627 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3629 victim->jointVel(abdomen) += relative * damagemult * 200;
3630 victim->Puff(abdomen);
3631 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3633 award_bonus(id, Reversal);
3636 if (hasvictim && animCurrent == sneakattackanim && currentFrame().label == 7) {
3639 victim->skeleton.spinny = 0;
3641 relative = facing * -1;
3643 Normalise(&relative);
3644 if (victim->id == 0) {
3647 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3648 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3650 victim->damage = victim->damagetolerance;
3651 victim->permanentdamage = victim->damagetolerance - 1;
3653 if (weaponactive == -1) {
3654 doslice = PersonType::types[creature].hasClaws;
3656 doslice = (weapons[weaponids[0]].getType() != staff);
3659 if (weaponactive == -1) {
3660 emit_sound_at(clawslicesound, victim->coords, 128.);
3662 victim->DoBloodBig(2, 175);
3664 victim->DoBloodBig(200, 225);
3665 emit_sound_at(knifeslicesound, victim->coords);
3667 weapons[weaponids[weaponactive]].bloody = 2;
3669 weapons[weaponids[weaponactive]].blooddrip += 5;
3672 award_bonus(id, spinecrusher);
3675 if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 5) {
3676 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3678 if (animTarget == knifefollowanim) {
3679 victim->DoBloodBig(200, 210);
3681 if (animTarget == knifesneakattackanim) {
3682 XYZ footvel, footpoint;
3684 footpoint = weapons[weaponids[0]].tippoint;
3686 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3688 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3689 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3690 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3691 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3692 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3693 victim->DoBloodBig(200, 195);
3694 award_bonus(id, tracheotomy);
3696 if (animTarget == knifefollowanim) {
3697 award_bonus(id, Stabbonus);
3698 XYZ footvel, footpoint;
3700 footpoint = weapons[weaponids[0]].tippoint;
3702 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3704 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3705 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3706 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3707 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3708 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3710 victim->bloodloss += 10000;
3711 victim->velocity = 0;
3712 emit_sound_at(fleshstabsound, victim->coords);
3714 weapons[weaponids[weaponactive]].bloody = 2;
3716 weapons[weaponids[weaponactive]].blooddrip += 5;
3720 if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 6) {
3722 victim->velocity = 0;
3723 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3724 victim->skeleton.joints[i].velocity = 0;
3726 if (animTarget == knifefollowanim) {
3728 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3729 victim->skeleton.joints[i].velocity = 0;
3732 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3733 emit_sound_at(fleshstabremovesound, victim->coords);
3735 weapons[weaponids[weaponactive]].bloody = 2;
3737 weapons[weaponids[weaponactive]].blooddrip += 5;
3739 XYZ footvel, footpoint;
3741 footpoint = weapons[weaponids[0]].tippoint;
3743 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3745 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3746 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3747 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3748 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3749 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3753 if (hasvictim && (animCurrent == swordsneakattackanim) && currentFrame().label == 5) {
3754 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3755 award_bonus(id, backstab);
3759 XYZ footvel, footpoint;
3761 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3763 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3765 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3766 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3767 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3768 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3769 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3770 victim->DoBloodBig(200, 180);
3771 victim->DoBloodBig(200, 215);
3772 victim->bloodloss += 10000;
3773 victim->velocity = 0;
3774 emit_sound_at(fleshstabsound, victim->coords);
3776 weapons[weaponids[weaponactive]].bloody = 2;
3778 weapons[weaponids[weaponactive]].blooddrip += 5;
3782 if (hasvictim && animCurrent == swordsneakattackanim && currentFrame().label == 6) {
3784 victim->velocity = 0;
3785 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3786 victim->skeleton.joints[i].velocity = 0;
3788 if (weaponactive != -1) {
3789 emit_sound_at(fleshstabremovesound, victim->coords);
3791 weapons[weaponids[weaponactive]].bloody = 2;
3793 weapons[weaponids[weaponactive]].blooddrip += 5;
3795 XYZ footvel, footpoint;
3797 footpoint = weapons[weaponids[0]].tippoint;
3799 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3801 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3802 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3803 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3804 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3805 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3809 if (animCurrent == sweepreversalanim && currentFrame().label == 7) {
3818 if (weaponactive == -1) {
3819 if (!Tutorial::active) {
3820 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3824 if (weaponactive == -1) {
3825 doslice = PersonType::types[creature].hasClaws;
3827 doslice = (weapons[weaponids[0]].getType() != staff);
3830 if (weaponactive == -1) {
3831 emit_sound_at(clawslicesound, victim->coords, 128.);
3833 victim->DoBloodBig(2 / victim->armorhead, 175);
3835 victim->DoBloodBig(2 / victim->armorhead, 225);
3836 emit_sound_at(knifeslicesound, victim->coords);
3837 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3838 weapons[weaponids[weaponactive]].bloody = 1;
3840 weapons[weaponids[weaponactive]].blooddrip += 3;
3844 award_bonus(id, Reversal);
3849 relative = facing * -1;
3851 Normalise(&relative);
3852 relative = DoRotation(relative, 0, 90, 0);
3854 Normalise(&relative);
3855 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3856 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3858 victim->jointVel(head) += relative * damagemult * 200;
3859 if (victim->damage < victim->damagetolerance - 100) {
3860 victim->velocity = relative * 200;
3862 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3863 victim->velocity = 0;
3866 if (animCurrent == sweepreversalanim && ((currentFrame().label == 9 && victim->damage < victim->damagetolerance) || (currentFrame().label == 7 && victim->damage > victim->damagetolerance))) {
3870 relative = facing * -1;
3872 Normalise(&relative);
3873 relative = DoRotation(relative, 0, 90, 0);
3875 Normalise(&relative);
3876 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3877 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3879 victim->jointVel(head) += relative * damagemult * 200;
3882 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
3883 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3884 award_bonus(id, reverseko);
3890 if (frameTarget >= int(Animation::animations[animCurrent].frames.size())) {
3893 animTarget = getIdle();
3894 FootLand(leftfoot, 1);
3895 FootLand(rightfoot, 1);
3897 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3898 animTarget = rollanim;
3900 emit_sound_at(movewhooshsound, coords, 128.);
3902 if (animCurrent == staggerbackhighanim) {
3903 animTarget = getIdle();
3905 if (animCurrent == staggerbackhardanim) {
3906 animTarget = getIdle();
3908 if (animCurrent == removeknifeanim) {
3909 animTarget = getIdle();
3911 if (animCurrent == crouchremoveknifeanim) {
3912 animTarget = getCrouch();
3914 if (animCurrent == backhandspringanim) {
3915 animTarget = getIdle();
3917 if (animCurrent == dodgebackanim) {
3918 animTarget = getIdle();
3920 if (animCurrent == drawleftanim) {
3921 animTarget = getIdle();
3923 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3924 animTarget = getIdle();
3925 if (animCurrent == crouchdrawrightanim) {
3926 animTarget = getCrouch();
3928 if (weaponactive == -1) {
3930 } else if (weaponactive == 0) {
3932 if (num_weapons == 2) {
3934 buffer = weaponids[0];
3935 weaponids[0] = weaponids[1];
3936 weaponids[1] = buffer;
3940 if (weaponactive == -1) {
3941 emit_sound_at(knifesheathesound, coords, 128.);
3943 if (weaponactive != -1) {
3944 emit_sound_at(knifedrawsound, coords, 128.);
3947 if (animCurrent == rollanim) {
3948 animTarget = getCrouch();
3949 FootLand(leftfoot, 1);
3950 FootLand(rightfoot, 1);
3953 if (animTarget == walljumprightkickanim) {
3956 if (animTarget == walljumpleftkickanim) {
3959 animTarget = jumpdownanim;
3961 if (animCurrent == climbanim) {
3962 animTarget = getCrouch();
3964 coords += facing * .1;
3965 if (!isnormal(coords.x)) {
3976 if (animTarget == rabbitkickreversalanim) {
3977 animTarget = getCrouch();
3980 if (animTarget == jumpreversalanim) {
3981 animTarget = getCrouch();
3984 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3985 if (attackkeydown && animTarget != walljumpfrontanim) {
3987 float closestdist = -1;
3989 if (Person::players.size() > 1) {
3990 for (unsigned i = 0; i < Person::players.size(); i++) {
3991 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3992 distance = distsq(&Person::players[i]->coords, &coords);
3993 if (closestdist == -1 || distance < closestdist) {
3994 closestdist = distance;
4000 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4001 victim = Person::players[closest];
4002 animTarget = walljumprightkickanim;
4004 XYZ rotatetarget = victim->coords - coords;
4005 Normalise(&rotatetarget);
4006 yaw = -asin(0 - rotatetarget.x);
4008 if (rotatetarget.z < 0) {
4011 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4012 velocity = (victim->coords - coords) * 4;
4017 if (animTarget == walljumpbackanim) {
4018 animTarget = backflipanim;
4020 velocity = facing * -8;
4023 resume_stream(whooshsound);
4026 if (animTarget == walljumprightanim) {
4027 animTarget = rightflipanim;
4031 velocity = DoRotation(facing, 0, 30, 0) * -8;
4034 if (animTarget == walljumpfrontanim) {
4035 animTarget = frontflipanim;
4039 velocity = facing * 8;
4043 resume_stream(whooshsound);
4046 if (animTarget == walljumpleftanim) {
4047 if (attackkeydown) {
4049 float closestdist = -1;
4051 if (Person::players.size() > 1) {
4052 for (unsigned i = 0; i < Person::players.size(); i++) {
4053 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4054 distance = distsq(&Person::players[i]->coords, &coords);
4055 if (closestdist == -1 || distance < closestdist) {
4056 closestdist = distance;
4062 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4063 victim = Person::players[closest];
4064 animTarget = walljumpleftkickanim;
4066 XYZ rotatetarget = victim->coords - coords;
4067 Normalise(&rotatetarget);
4068 yaw = -asin(0 - rotatetarget.x);
4070 if (rotatetarget.z < 0) {
4073 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4074 velocity = (victim->coords - coords) * 4;
4079 if (animTarget != walljumpleftkickanim) {
4080 animTarget = leftflipanim;
4084 velocity = DoRotation(facing, 0, -30, 0) * -8;
4088 resume_stream(whooshsound);
4091 if (animTarget == sneakattackanim) {
4092 animCurrent = getCrouch();
4093 animTarget = getCrouch();
4100 transspeed = 1000000;
4101 targetheadyaw += 180;
4102 coords -= facing * .7;
4104 coords.y = terrain.getHeight(coords.x, coords.z);
4109 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4110 animTarget = getIdle();
4113 coords.y = terrain.getHeight(coords.x, coords.z);
4118 if (animCurrent == knifefollowanim) {
4119 animTarget = getIdle();
4122 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4123 float ycoords = oldcoords.y;
4124 animTarget = getStop();
4129 transspeed = 1000000;
4130 targetheadyaw += 180;
4131 if (!isnormal(coords.x)) {
4134 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4135 oldcoords = coords + facing * .5;
4136 } else if (animCurrent == sweepreversalanim) {
4137 oldcoords = coords + facing * 1.1;
4138 } else if (animCurrent == upunchreversalanim) {
4139 oldcoords = coords + facing * 1.5;
4142 targetheadyaw += 180;
4145 } else if (animCurrent == knifeslashreversalanim) {
4146 oldcoords = coords + facing * .5;
4149 targetheadyaw += 90;
4152 } else if (animCurrent == staffspinhitreversalanim) {
4155 targetheadyaw += 180;
4160 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4162 oldcoords.y = ycoords;
4164 currentoffset = coords - oldcoords;
4170 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4175 if (Animation::animations[animTarget].attack == reversed) {
4177 if (animTarget == sweepreversedanim) {
4180 animTarget = backhandspringanim;
4182 emit_sound_at(landsound, coords, 128);
4184 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4185 animTarget = rollanim;
4188 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4189 coords.y = oldcoords.y;
4191 if (animCurrent == knifeslashreversedanim) {
4192 animTarget = rollanim;
4197 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4198 coords.y = oldcoords.y;
4202 animTarget = jumpdownanim;
4205 animTarget = getIdle();
4207 if (wasLandhard()) {
4208 animTarget = getIdle();
4210 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4211 animTarget = getIdle();
4213 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4214 coords.y = oldcoords.y;
4215 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4216 targetoffset.y = coords.y;
4218 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4220 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4221 currentoffset.y -= (coords.y - targetoffset.y);
4222 coords.y = targetoffset.y;
4224 normalsupdatedelay = 0;
4226 if (animCurrent == upunchanim) {
4227 animTarget = getStop();
4228 normalsupdatedelay = 0;
4231 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4235 if (num_weapons > 0) {
4236 if (weapons[0].getType() == staff) {
4245 rabbitkickragdoll = 1;
4247 if (animCurrent == rabbitkickreversedanim) {
4253 skeleton.spinny = 0;
4254 SolidHitBonus(!id); // FIXME: tricky id
4258 animTarget = rollanim;
4261 pause_sound(whooshsound);
4266 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4270 skeleton.spinny = 0;
4272 if (animCurrent == jumpreversedanim) {
4278 skeleton.spinny = 0;
4279 SolidHitBonus(!id); // FIXME: tricky id
4283 animTarget = rollanim;
4284 coords += facing * 2;
4286 pause_sound(whooshsound);
4292 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) {
4293 animTarget = getupfromfrontanim;
4295 } else if (Animation::animations[animCurrent].attack == normalattack) {
4296 animTarget = getIdle();
4299 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4300 animTarget = blockhighleftstrikeanim;
4302 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4303 animTarget = getIdle();
4306 if (animCurrent == spinkickanim && victim->skeleton.free) {
4307 if (creature == rabbittype) {
4308 animTarget = fightidleanim;
4314 if (isIdle() && !wasIdle()) {
4315 normalsupdatedelay = 0;
4318 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4319 animTarget = jumpdownanim;
4322 if (!skeleton.free) {
4324 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4325 if (!isRun() || !wasRun()) {
4326 if (targetFrame().speed > currentFrame().speed) {
4327 target += multiplier * targetFrame().speed * speed * 2;
4329 if (targetFrame().speed <= currentFrame().speed) {
4330 target += multiplier * currentFrame().speed * speed * 2;
4333 if (isRun() && wasRun()) {
4335 tempspeed = velspeed;
4336 if (tempspeed < 10 * speedmult) {
4337 tempspeed = 10 * speedmult;
4339 /* FIXME - mixed of target and current here, is that intended? */
4340 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4342 } else if (transspeed) {
4343 target += multiplier * transspeed * speed * 2;
4345 if (!isRun() || !wasRun()) {
4346 if (targetFrame().speed > currentFrame().speed) {
4347 target += multiplier * targetFrame().speed * 2;
4349 if (targetFrame().speed <= currentFrame().speed) {
4350 target += multiplier * currentFrame().speed * 2;
4355 if (animCurrent != animTarget) {
4356 target = (target + oldtarget) / 2;
4360 frameCurrent = frameTarget;
4364 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4365 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4369 rot = targetrot * target;
4370 yaw += rot - oldrot;
4377 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4379 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4380 skeleton.joints[i].position = currentFrame().joints[i].position;
4383 skeleton.FindForwards();
4385 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4386 if (skeleton.muscles[i].visible) {
4387 skeleton.FindRotationMuscle(i, animTarget);
4390 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4391 if (skeleton.muscles[i].visible) {
4392 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4393 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4395 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4396 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4398 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4399 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4405 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4406 skeleton.joints[i].position = targetFrame().joints[i].position;
4409 skeleton.FindForwards();
4411 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4412 if (skeleton.muscles[i].visible) {
4413 skeleton.FindRotationMuscle(i, animTarget);
4416 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4417 if (skeleton.muscles[i].visible) {
4418 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4419 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4421 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4422 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4424 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4425 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4427 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4428 skeleton.muscles[i].newrotate3 -= 360;
4430 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4431 skeleton.muscles[i].newrotate3 += 360;
4433 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4434 skeleton.muscles[i].newrotate2 -= 360;
4436 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4437 skeleton.muscles[i].newrotate2 += 360;
4439 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4440 skeleton.muscles[i].newrotate1 -= 360;
4442 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4443 skeleton.muscles[i].newrotate1 += 360;
4449 oldanimCurrent = animCurrent;
4450 oldanimTarget = animTarget;
4451 oldframeTarget = frameTarget;
4452 oldframeCurrent = frameCurrent;
4454 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4455 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4456 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4458 offset = currentoffset * (1 - target) + targetoffset * target;
4459 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4460 if (skeleton.muscles[i].visible) {
4461 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4462 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4463 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4468 if (isLanding() && landhard) {
4472 animTarget = getLandhard();
4485 void Person::DoStuff()
4487 static XYZ terrainnormal;
4488 static XYZ flatfacing;
4489 static XYZ flatvelocity;
4490 static float flatvelspeed;
4491 static int bloodsize;
4492 static int startx, starty, endx, endy;
4493 static GLubyte color;
4494 static XYZ bloodvel;
4496 onfiredelay -= multiplier;
4497 if (onfiredelay < 0 && onfire) {
4498 if (Random() % 2 == 0) {
4504 crouchkeydowntime += multiplier;
4505 if (!crouchkeydown) {
4506 crouchkeydowntime = 0;
4508 jumpkeydowntime += multiplier;
4509 if (!jumpkeydown && skeleton.free) {
4510 jumpkeydowntime = 0;
4513 if (hostile || damage > 0 || bloodloss > 0) {
4517 if (isIdle() || isRun()) {
4521 if (num_weapons == 1 && weaponactive != -1) {
4526 blooddimamount -= multiplier * .3;
4528 speechdelay -= multiplier;
4529 texupdatedelay -= multiplier;
4530 interestdelay -= multiplier;
4531 flamedelay -= multiplier;
4532 parriedrecently -= multiplier;
4534 victim = this->shared_from_this();
4539 speed = 1.1 * speedmult;
4541 speed = 1.0 * speedmult;
4543 if (!skeleton.free) {
4544 rabbitkickragdoll = 0;
4549 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4552 if (id != 0 && creature == wolftype && difficulty == 2) {
4554 if (aitype != passivetype) {
4556 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) {
4563 if (animTarget == wolfrunninganim && !superruntoggle) {
4564 animTarget = getRun();
4568 if (weaponactive == -1 && num_weapons > 0) {
4569 if (weapons[weaponids[0]].getType() == staff) {
4575 burnt += multiplier;
4580 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4582 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4589 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4590 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4594 while (flamedelay < 0 && onfire) {
4596 int howmany = fabs(Random() % (skeleton.joints.size()));
4597 if (skeleton.free) {
4598 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4599 flatfacing = skeleton.joints[howmany].position * scale + coords;
4601 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4602 flatvelocity = (coords - oldcoords) / multiplier / 2;
4604 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4607 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4609 int howmany = fabs(Random() % (skeleton.joints.size()));
4610 if (skeleton.free) {
4611 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4612 flatfacing = skeleton.joints[howmany].position * scale + coords;
4614 flatvelocity = (coords - oldcoords) / multiplier / 2;
4615 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4617 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4621 bleeding -= multiplier * .3;
4622 if (bloodtoggle == 2) {
4623 skeleton.drawmodel.textureptr.bind();
4624 if ((bleeding <= 0) && (detail != 2)) {
4630 if (neckspurtamount > 0) {
4631 neckspurtamount -= multiplier;
4632 neckspurtdelay -= multiplier * 3;
4633 neckspurtparticledelay -= multiplier * 3;
4634 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4637 if (skeleton.free) {
4638 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4639 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4640 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4642 bloodvel.z = 5 * neckspurtamount;
4643 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4644 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4645 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4647 neckspurtparticledelay = .05;
4649 if (neckspurtdelay < 0) {
4654 if (deathbleeding > 0 && dead != 2) {
4655 if (deathbleeding < 5) {
4656 bleeddelay -= deathbleeding * multiplier / 4;
4658 bleeddelay -= 5 * multiplier / 4;
4660 if (bleeddelay < 0 && bloodtoggle) {
4665 if (skeleton.free) {
4666 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4667 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4669 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4670 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4674 bloodloss += deathbleeding * multiplier * 80;
4675 deathbleeding -= multiplier * 1.6;
4676 if (deathbleeding < 0) {
4679 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4680 if (weaponactive != -1) {
4681 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4682 weapons[weaponids[0]].velocity.x += .01;
4685 weaponids[0] = weaponids[num_weapons];
4686 if (weaponstuck == num_weapons) {
4691 for (unsigned i = 0; i < Person::players.size(); i++) {
4692 Person::players[i]->wentforweapon = 0;
4700 if (!dead && creature == wolftype) {
4701 award_bonus(0, Wolfbonus);
4704 if (animTarget == knifefollowedanim && !skeleton.free) {
4705 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4706 skeleton.joints[i].velocity = 0;
4707 skeleton.joints[i].velocity.y = -2;
4710 if (id != 0 && unconscioustime > .1) {
4718 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4719 texupdatedelay = .12;
4721 bloodsize = 5 - realtexdetail;
4725 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4726 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4727 endx = startx + bloodsize;
4728 endy = starty + bloodsize;
4738 if (endx > skeleton.skinsize - 1) {
4739 endx = skeleton.skinsize - 1;
4742 if (endy > skeleton.skinsize - 1) {
4743 endy = skeleton.skinsize - 1;
4746 if (endx < startx) {
4749 if (endy < starty) {
4753 for (int i = startx; i < endx; i++) {
4754 for (int j = starty; j < endy; j++) {
4755 if (Random() % 2 == 0) {
4756 color = Random() % 85 + 170;
4757 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4758 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4760 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4761 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4766 skeleton.drawmodel.textureptr.bind();
4770 if (skeleton.free) {
4771 bleedx += 4 * direction / realtexdetail;
4773 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4775 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4778 bleedy -= 4 / realtexdetail;
4780 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4782 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4787 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4788 righthandmorphness = targetrighthandmorphness;
4789 righthandmorphstart = righthandmorphend;
4790 } else if (righthandmorphness > targetrighthandmorphness) {
4791 righthandmorphness -= multiplier * 4;
4792 } else if (righthandmorphness < targetrighthandmorphness) {
4793 righthandmorphness += multiplier * 4;
4796 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4797 lefthandmorphness = targetlefthandmorphness;
4798 lefthandmorphstart = lefthandmorphend;
4799 } else if (lefthandmorphness > targetlefthandmorphness) {
4800 lefthandmorphness -= multiplier * 4;
4801 } else if (lefthandmorphness < targetlefthandmorphness) {
4802 lefthandmorphness += multiplier * 4;
4805 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4806 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4807 tailmorphness = targettailmorphness;
4808 tailmorphstart = tailmorphend;
4809 } else if (tailmorphness > targettailmorphness) {
4810 tailmorphness -= multiplier * 10;
4811 } else if (tailmorphness < targettailmorphness) {
4812 tailmorphness += multiplier * 10;
4816 if (creature == wolftype) {
4817 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4818 tailmorphness = targettailmorphness;
4819 tailmorphstart = tailmorphend;
4820 } else if (tailmorphness > targettailmorphness) {
4821 tailmorphness -= multiplier * 2;
4822 } else if (tailmorphness < targettailmorphness) {
4823 tailmorphness += multiplier * 2;
4827 if (headmorphend == 3 || headmorphstart == 3) {
4828 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4829 headmorphness = targetheadmorphness;
4830 headmorphstart = headmorphend;
4831 } else if (headmorphness > targetheadmorphness) {
4832 headmorphness -= multiplier * 7;
4833 } else if (headmorphness < targetheadmorphness) {
4834 headmorphness += multiplier * 7;
4836 } else if (headmorphend == 5 || headmorphstart == 5) {
4837 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4838 headmorphness = targetheadmorphness;
4839 headmorphstart = headmorphend;
4840 } else if (headmorphness > targetheadmorphness) {
4841 headmorphness -= multiplier * 10;
4842 } else if (headmorphness < targetheadmorphness) {
4843 headmorphness += multiplier * 10;
4846 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4847 headmorphness = targetheadmorphness;
4848 headmorphstart = headmorphend;
4849 } else if (headmorphness > targetheadmorphness) {
4850 headmorphness -= multiplier * 4;
4851 } else if (headmorphness < targetheadmorphness) {
4852 headmorphness += multiplier * 4;
4856 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4857 chestmorphness = targetchestmorphness;
4858 chestmorphstart = chestmorphend;
4859 } else if (chestmorphness > targetchestmorphness) {
4860 chestmorphness -= multiplier;
4861 } else if (chestmorphness < targetchestmorphness) {
4862 chestmorphness += multiplier;
4865 if (dead != 2 && howactive <= typesleeping) {
4866 if (chestmorphstart == 0 && chestmorphend == 0) {
4868 targetchestmorphness = 1;
4871 if (chestmorphstart != 0 && chestmorphend != 0) {
4873 targetchestmorphness = 1;
4875 if (environment == snowyenvironment) {
4878 if (skeleton.free) {
4879 footvel = skeleton.specialforward[0] * -1;
4880 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4882 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4883 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4885 if (animTarget == sleepanim) {
4886 footvel = DoRotation(footvel, 0, 90, 0);
4888 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4892 if (!dead && howactive < typesleeping) {
4893 blinkdelay -= multiplier * 2;
4894 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4896 targetheadmorphness = 1;
4898 blinkdelay = (float)(abs(Random() % 40)) / 5;
4900 if (headmorphstart == 3 && headmorphend == 3) {
4902 targetheadmorphness = 1;
4907 twitchdelay -= multiplier * 1.5;
4908 if (animTarget != hurtidleanim) {
4909 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4911 targetheadmorphness = 1;
4913 twitchdelay = (float)(abs(Random() % 40)) / 5;
4915 if (headmorphstart == 5 && headmorphend == 5) {
4917 targetheadmorphness = 1;
4921 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4922 twitchdelay3 -= multiplier * 1;
4923 if (Random() % 2 == 0) {
4924 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4925 righthandmorphness = 0;
4926 targetrighthandmorphness = 1;
4927 righthandmorphend = 1;
4928 if (Random() % 2 == 0) {
4929 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4932 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4933 righthandmorphness = 0;
4934 targetrighthandmorphness = 1;
4935 righthandmorphend = 0;
4938 if (Random() % 2 == 0) {
4939 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4940 lefthandmorphness = 0;
4941 targetlefthandmorphness = 1;
4942 lefthandmorphend = 1;
4943 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4945 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4946 lefthandmorphness = 0;
4947 targetlefthandmorphness = 1;
4948 lefthandmorphend = 0;
4954 if (creature == rabbittype) {
4955 if (howactive < typesleeping) {
4956 twitchdelay2 -= multiplier * 1.5;
4958 twitchdelay2 -= multiplier * 0.5;
4960 if (howactive <= typesleeping) {
4961 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4963 targettailmorphness = 1;
4965 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4967 if (tailmorphstart == 1 && tailmorphend == 1) {
4969 targettailmorphness = 1;
4972 if (tailmorphstart == 2 && tailmorphend == 2) {
4974 targettailmorphness = 1;
4981 if (creature == wolftype) {
4982 twitchdelay2 -= multiplier * 1.5;
4983 if (tailmorphend != 0) {
4984 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4986 targettailmorphness = 1;
4991 if (tailmorphend != 5) {
4992 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4994 targettailmorphness = 1;
4999 if (twitchdelay2 <= 0) {
5000 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5002 targettailmorphness = 1;
5005 if (tailmorphstart == 1 && tailmorphend == 1) {
5007 targettailmorphness = 1;
5010 if (tailmorphstart == 2 && tailmorphend == 2) {
5012 targettailmorphness = 1;
5015 if (tailmorphstart == 3 && tailmorphend == 3) {
5017 targettailmorphness = 1;
5020 if (tailmorphstart == 4 && tailmorphend == 4) {
5022 targettailmorphness = 1;
5029 unconscioustime = 0;
5032 if (dead == 1 || howactive == typesleeping) {
5033 unconscioustime += multiplier;
5034 //If unconscious, close eyes and mouth
5035 if (righthandmorphend != 0) {
5036 righthandmorphness = 0;
5038 righthandmorphend = 0;
5039 targetrighthandmorphness = 1;
5041 if (lefthandmorphend != 0) {
5042 lefthandmorphness = 0;
5044 lefthandmorphend = 0;
5045 targetlefthandmorphness = 1;
5047 if (headmorphend != 3 && headmorphend != 5) {
5051 targetheadmorphness = 1;
5054 if (howactive > typesleeping) {
5057 if (bloodtoggle && !bled) {
5058 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5059 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5060 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5061 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5065 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5071 if (dead == 2 || howactive > typesleeping) {
5072 //If dead, open mouth and hands
5073 if (righthandmorphend != 0) {
5074 righthandmorphness = 0;
5076 righthandmorphend = 0;
5077 targetrighthandmorphness = 1;
5079 if (lefthandmorphend != 0) {
5080 lefthandmorphness = 0;
5082 lefthandmorphend = 0;
5083 targetlefthandmorphness = 1;
5085 if (headmorphend != 2) {
5089 targetheadmorphness = 1;
5092 if (stunned > 0 && !dead && headmorphend != 2) {
5093 if (headmorphend != 4) {
5097 targetheadmorphness = 1;
5100 if (damage > damagetolerance && !dead) {
5103 unconscioustime = 0;
5105 if (creature == wolftype) {
5106 award_bonus(0, Wolfbonus);
5111 if (weaponactive != -1) {
5112 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5113 weapons[weaponids[0]].velocity.x += .01;
5116 weaponids[0] = weaponids[num_weapons];
5117 if (weaponstuck == num_weapons) {
5122 for (unsigned i = 0; i < Person::players.size(); i++) {
5123 Person::players[i]->wentforweapon = 0;
5127 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5136 damage -= multiplier * 13;
5137 permanentdamage -= multiplier * 4;
5138 if (isIdle() || isCrouch()) {
5139 permanentdamage -= multiplier * 4;
5145 if (permanentdamage < 0) {
5146 permanentdamage = 0;
5148 if (superpermanentdamage < 0) {
5149 superpermanentdamage = 0;
5151 if (permanentdamage < superpermanentdamage) {
5152 permanentdamage = superpermanentdamage;
5154 if (damage < permanentdamage) {
5155 damage = permanentdamage;
5157 if (dead == 1 && damage < damagetolerance) {
5161 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5162 skeleton.joints[i].velocity = 0;
5165 if (permanentdamage > damagetolerance && dead != 2) {
5168 if (weaponactive != -1) {
5169 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5170 weapons[weaponids[0]].velocity.x += .01;
5173 weaponids[0] = weaponids[num_weapons];
5174 if (weaponstuck == num_weapons) {
5179 for (unsigned i = 0; i < Person::players.size(); i++) {
5180 Person::players[i]->wentforweapon = 0;
5186 if (!dead && creature == wolftype) {
5187 award_bonus(0, Wolfbonus);
5190 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5191 award_bonus(id, touchofdeath);
5193 if (id != 0 && unconscioustime > .1) {
5201 emit_sound_at(breaksound, coords);
5204 if (skeleton.free == 1) {
5206 pause_sound(whooshsound);
5210 //If knocked over, open hands and close mouth
5211 if (righthandmorphend != 0) {
5212 righthandmorphness = 0;
5214 righthandmorphend = 0;
5215 targetrighthandmorphness = 1;
5217 if (lefthandmorphend != 0) {
5218 lefthandmorphness = 0;
5220 lefthandmorphend = 0;
5221 targetlefthandmorphness = 1;
5223 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5224 if (headmorphend != 0) {
5228 targetheadmorphness = 1;
5232 skeleton.DoGravity(&scale);
5234 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5235 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5236 award_bonus(id, deepimpact);
5238 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5242 if (!skeleton.joints.empty()) {
5243 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5244 average += skeleton.joints[j].position;
5246 average /= skeleton.joints.size();
5247 coords += average * scale;
5248 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5249 skeleton.joints[j].position -= average;
5251 average /= multiplier;
5255 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5256 velocity += skeleton.joints[i].velocity * scale;
5258 velocity /= skeleton.joints.size();
5260 if (!isnormal(velocity.x) && velocity.x) {
5264 if (findLength(&average) < 10 && dead && skeleton.free) {
5265 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5266 if (skeleton.longdead > 2000) {
5267 if (skeleton.longdead > 6000) {
5269 pause_sound(whooshsound);
5275 if (dead == 2 && bloodloss < damagetolerance) {
5277 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5279 if (bloodtoggle && !bled) {
5280 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5281 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5282 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5283 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5284 float size = .2 * 1.2;
5287 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5292 if (dead == 2 && bloodloss >= damagetolerance) {
5294 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5295 if (bleeding <= 0) {
5298 if (bloodtoggle && !bled) {
5299 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5300 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5301 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5302 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5306 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5314 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5315 bool canrecover = 1;
5316 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5317 startpoint = coords;
5320 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5323 if (velocity.y < -30) {
5326 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5327 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5328 colviewer = startpoint;
5329 coltarget = endpoint;
5330 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5340 terrainnormal = jointPos(groin) - jointPos(abdomen);
5341 if (joint(groin).locked && joint(abdomen).locked) {
5342 terrainnormal = jointPos(groin) - jointPos(abdomen);
5343 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5345 if (joint(abdomen).locked && joint(neck).locked) {
5346 terrainnormal = jointPos(abdomen) - jointPos(neck);
5347 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5349 if (joint(groin).locked && joint(neck).locked) {
5350 terrainnormal = jointPos(groin) - jointPos(neck);
5351 middle = (jointPos(groin) + jointPos(neck)) / 2;
5353 Normalise(&terrainnormal);
5355 targetyaw = -asin(0 - terrainnormal.x);
5356 targetyaw *= 360 / 6.28;
5357 if (terrainnormal.z < 0) {
5358 targetyaw = 180 - targetyaw;
5363 animTarget = flipanim;
5364 crouchtogglekeydown = 1;
5369 animCurrent = tempanim;
5373 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5374 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5375 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5380 if (findLength(&average) < 10 && !dead && skeleton.free) {
5381 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5382 if (skeleton.longdead > (damage + 500) * 1.5) {
5384 pause_sound(whooshsound);
5391 terrainnormal = jointPos(groin) - jointPos(abdomen);
5392 if (joint(groin).locked && joint(abdomen).locked) {
5393 terrainnormal = jointPos(groin) - jointPos(abdomen);
5394 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5396 if (joint(abdomen).locked && joint(neck).locked) {
5397 terrainnormal = jointPos(abdomen) - jointPos(neck);
5398 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5400 if (joint(groin).locked && joint(neck).locked) {
5401 terrainnormal = jointPos(groin) - jointPos(neck);
5402 middle = (jointPos(groin) + jointPos(neck)) / 2;
5404 Normalise(&terrainnormal);
5406 targetyaw = -asin(0 - terrainnormal.x);
5407 targetyaw *= 360 / 6.28;
5408 if (terrainnormal.z < 0) {
5409 targetyaw = 180 - targetyaw;
5413 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5415 if (skeleton.forward.y < 0) {
5416 animTarget = getupfrombackanim;
5420 if (skeleton.forward.y > -.3) {
5421 animTarget = getupfromfrontanim;
5429 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5430 animTarget = rollanim;
5431 targetyaw = lookyaw;
5435 if (forwardkeydown) {
5444 if (forwardkeydown) {
5452 if (!leftkeydown && !rightkeydown) {
5460 if (abs(targettilt2) > 50) {
5463 animCurrent = tempanim;
5466 tilt2 = targettilt2;
5468 if (middle.y > 0 && animTarget != rollanim) {
5469 targetoffset.y = middle.y + 1;
5472 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5473 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5474 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5481 if (num_weapons > 0) {
5482 if (weapons[0].getType() == staff) {
5486 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5487 if (velocity.y > -30) {
5489 tempvelocity = velocity;
5490 Normalise(&tempvelocity);
5491 targetyaw = -asin(0 - tempvelocity.x);
5492 targetyaw *= 360 / 6.28;
5493 if (velocity.z < 0) {
5494 targetyaw = 180 - targetyaw;
5499 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5500 animTarget = rollanim;
5503 animTarget = backhandspringanim;
5509 emit_sound_at(movewhooshsound, coords, 128.);
5511 animCurrent = animTarget;
5512 frameCurrent = frameTarget - 1;
5524 if (skeleton.freefall == 0) {
5529 if (aitype != passivetype || skeleton.free == 1) {
5530 if (findLengthfast(&velocity) > .1) {
5531 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5532 if (Object::objects[i]->type == firetype) {
5533 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) {
5535 if (!Object::objects[i]->onfire) {
5536 emit_sound_at(firestartsound, Object::objects[i]->position);
5538 Object::objects[i]->onfire = 1;
5541 if (Object::objects[i]->onfire) {
5547 if (Object::objects[i]->type == bushtype) {
5548 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) {
5550 if (!Object::objects[i]->onfire) {
5551 emit_sound_at(firestartsound, Object::objects[i]->position);
5553 Object::objects[i]->onfire = 1;
5557 if (Object::objects[i]->onfire) {
5561 if (Object::objects[i]->messedwith <= 0) {
5565 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5568 addEnvSound(coords, 4 * findLength(&velocity));
5572 if (environment == grassyenvironment) {
5573 howmany = findLength(&velocity) * 4;
5575 if (environment == snowyenvironment) {
5576 howmany = findLength(&velocity) * 2;
5579 if (environment != desertenvironment) {
5580 for (int j = 0; j < howmany; j++) {
5581 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5582 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5583 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5586 pos.x += float(abs(Random() % 100) - 50) / 200;
5587 pos.y += float(abs(Random() % 100) - 50) / 200;
5588 pos.z += float(abs(Random() % 100) - 50) / 200;
5589 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);
5590 Sprite::setLastSpriteSpecial(1);
5594 howmany = findLength(&velocity) * 4;
5596 if (environment == snowyenvironment) {
5597 for (int j = 0; j < howmany; j++) {
5598 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5599 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5600 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5603 pos.x += float(abs(Random() % 100) - 50) / 200;
5604 pos.y += float(abs(Random() % 100) - 50) / 200;
5605 pos.z += float(abs(Random() % 100) - 50) / 200;
5606 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5607 Sprite::setLastSpriteSpecial(2);
5612 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5613 Object::objects[i]->roty += velocity.z * multiplier * 6;
5614 Object::objects[i]->messedwith = .5;
5618 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5619 if (Object::objects[i]->pitch == 0) {
5622 tempcoord = coords - Object::objects[i]->position;
5623 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5624 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5625 tempcoord += Object::objects[i]->position;
5627 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) {
5628 if (Object::objects[i]->messedwith <= 0) {
5632 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5635 addEnvSound(coords, 4 * findLength(&velocity));
5639 if (environment == grassyenvironment) {
5640 howmany = findLength(&velocity) * 4;
5642 if (environment == snowyenvironment) {
5643 howmany = findLength(&velocity) * 2;
5646 if (environment != desertenvironment) {
5647 for (int j = 0; j < howmany; j++) {
5648 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5649 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5650 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5652 pos += velocity * .1;
5654 pos.x += float(abs(Random() % 100) - 50) / 150;
5655 pos.y += float(abs(Random() % 100) - 50) / 150;
5656 pos.z += float(abs(Random() % 100) - 50) / 150;
5657 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);
5658 Sprite::setLastSpriteSpecial(1);
5662 howmany = findLength(&velocity) * 4;
5664 if (environment == snowyenvironment) {
5665 for (int j = 0; j < howmany; j++) {
5666 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5667 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5668 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5670 pos += velocity * .1;
5672 pos.x += float(abs(Random() % 100) - 50) / 150;
5673 pos.y += float(abs(Random() % 100) - 50) / 150;
5674 pos.z += float(abs(Random() % 100) - 50) / 150;
5675 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5676 Sprite::setLastSpriteSpecial(2);
5681 Object::objects[i]->messedwith = .5;
5688 if (!skeleton.free) {
5691 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5695 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5699 if (Tutorial::active && id != 0) {
5702 if (play && aitype != playercontrolled) {
5703 int whichsound = -1;
5704 if (speechdelay <= 0) {
5705 unsigned int i = abs(Random() % 4);
5707 whichsound = PersonType::types[creature].soundsTalk[i];
5712 if (whichsound != -1) {
5713 emit_sound_at(whichsound, coords);
5717 if (animTarget == staggerbackhighanim) {
5720 if (animTarget == staggerbackhardanim) {
5723 staggerdelay -= multiplier;
5724 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5727 if (velocity.y < -30 && animTarget == jumpdownanim) {
5730 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5731 animTarget = getIdle();
5735 weaponmissdelay -= multiplier;
5736 highreversaldelay -= multiplier;
5737 lowreversaldelay -= multiplier;
5738 lastcollide -= multiplier;
5739 skiddelay -= multiplier;
5740 if (!isnormal(velocity.x) && velocity.x) {
5743 if (!isnormal(targettilt) && targettilt) {
5746 if (!isnormal(targettilt2) && targettilt2) {
5749 if (!isnormal(targetyaw) && targetyaw) {
5753 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5754 //open hands and close mouth
5755 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5756 righthandmorphness = 0;
5757 righthandmorphend = 0;
5758 targetrighthandmorphness = 1;
5761 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5762 lefthandmorphness = 0;
5763 lefthandmorphend = 0;
5764 targetlefthandmorphness = 1;
5767 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5770 targetheadmorphness = 1;
5774 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) {
5775 //open hands and mouth
5776 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5777 righthandmorphness = 0;
5778 righthandmorphend = 0;
5779 targetrighthandmorphness = 1;
5782 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5783 lefthandmorphness = 0;
5784 lefthandmorphend = 0;
5785 targetlefthandmorphness = 1;
5788 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5791 targetheadmorphness = 1;
5795 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5796 //close hands and mouth
5797 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5798 righthandmorphness = 0;
5799 righthandmorphend = 1;
5800 targetrighthandmorphness = 1;
5803 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5804 lefthandmorphness = 0;
5805 lefthandmorphend = 1;
5806 targetlefthandmorphness = 1;
5809 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5812 targetheadmorphness = 1;
5816 if (animTarget == spinkickanim ||
5817 animTarget == staffspinhitreversalanim ||
5818 animTarget == staffspinhitreversedanim ||
5819 animTarget == staffhitreversalanim ||
5820 animTarget == staffhitreversedanim ||
5821 animTarget == hurtidleanim ||
5822 animTarget == winduppunchanim ||
5823 animTarget == swordslashreversalanim ||
5824 animTarget == swordslashreversedanim ||
5825 animTarget == knifeslashreversalanim ||
5826 animTarget == knifeslashreversedanim ||
5827 animTarget == knifethrowanim ||
5828 animTarget == knifefollowanim ||
5829 animTarget == knifefollowedanim ||
5830 animTarget == killanim ||
5831 animTarget == dropkickanim ||
5832 animTarget == upunchanim ||
5833 animTarget == knifeslashstartanim ||
5834 animTarget == swordslashanim ||
5835 animTarget == staffhitanim ||
5836 animTarget == staffspinhitanim ||
5837 animTarget == staffgroundsmashanim ||
5838 animTarget == spinkickreversalanim ||
5839 animTarget == sweepreversalanim ||
5840 animTarget == lowkickanim ||
5841 animTarget == sweepreversedanim ||
5842 animTarget == rabbitkickreversalanim ||
5843 animTarget == rabbitkickreversedanim ||
5844 animTarget == jumpreversalanim ||
5845 animTarget == jumpreversedanim) {
5846 //close hands and yell
5847 if (righthandmorphend != 1 &&
5848 righthandmorphness == targetrighthandmorphness) {
5849 righthandmorphness = 0;
5850 righthandmorphend = 1;
5851 targetrighthandmorphness = 1;
5854 if (lefthandmorphend != 1 &&
5855 lefthandmorphness == targetlefthandmorphness) {
5856 lefthandmorphness = 0;
5857 lefthandmorphend = 1;
5858 targetlefthandmorphness = 1;
5861 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5864 targetheadmorphness = 1;
5871 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5872 (victim->aitype != searchtype) && (aitype != passivetype) &&
5873 (aitype != searchtype) && (victim->id < Person::players.size())) {
5874 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5878 if (!dead && animTarget != hurtidleanim) {
5879 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5880 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5883 targetheadmorphness = 1;
5888 if (weaponactive != -1) {
5889 if (weapons[weaponids[weaponactive]].getType() != staff) {
5890 righthandmorphstart = 1;
5891 righthandmorphend = 1;
5893 if (weapons[weaponids[weaponactive]].getType() == staff) {
5894 righthandmorphstart = 2;
5895 righthandmorphend = 2;
5897 targetrighthandmorphness = 1;
5900 terrainnormal = terrain.getNormal(coords.x, coords.z);
5902 if (Animation::animations[animTarget].attack != reversal) {
5903 if (!isnormal(coords.x)) {
5912 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5913 facing = flatfacing;
5914 ReflectVector(&facing, terrainnormal);
5918 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5920 targettilt2 = -facing.y * 20;
5926 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
5929 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5930 flatvelocity = velocity;
5932 flatvelspeed = findLength(&flatvelocity);
5933 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5934 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5935 if (velocity.y < 0) {
5938 if (velocity.y < 0) {
5941 if (targettilt > 25) {
5944 if (targettilt < -25) {
5949 if (targettilt2 > 45) {
5952 if (targettilt2 < -45) {
5955 if (abs(tilt2 - targettilt2) < multiplier * 400) {
5956 tilt2 = targettilt2;
5957 } else if (tilt2 > targettilt2) {
5958 tilt2 -= multiplier * 400;
5959 } else if (tilt2 < targettilt2) {
5960 tilt2 += multiplier * 400;
5962 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5971 if (!isnormal(targettilt) && targettilt) {
5974 if (!isnormal(targettilt2) && targettilt2) {
5979 if (animTarget == rabbittackleanim) {
5980 velocity += facing * multiplier * speed * 700 * scale;
5981 velspeed = findLength(&velocity);
5982 if (velspeed > speed * 65 * scale) {
5983 velocity /= velspeed;
5984 velspeed = speed * 65 * scale;
5985 velocity *= velspeed;
5987 velocity.y += gravity * multiplier * 20;
5988 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5989 velspeed = findLength(&velocity);
5990 velocity = flatfacing * velspeed;
5992 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5993 if (isRun() || animTarget == rabbitkickanim) {
5994 velocity += facing * multiplier * speed * 700 * scale;
5995 velspeed = findLength(&velocity);
5996 if (velspeed > speed * 45 * scale) {
5997 velocity /= velspeed;
5998 velspeed = speed * 45 * scale;
5999 velocity *= velspeed;
6001 velocity.y += gravity * multiplier * 20;
6002 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6003 velspeed = findLength(&velocity);
6004 if (velspeed < speed * 30 * scale) {
6005 velspeed = speed * 30 * scale;
6007 velocity = flatfacing * velspeed;
6009 } else if (isRun()) {
6010 velocity += facing * multiplier * speed * 700 * scale;
6011 velspeed = findLength(&velocity);
6012 if (creature == rabbittype) {
6013 if (velspeed > speed * 55 * scale) {
6014 velocity /= velspeed;
6015 velspeed = speed * 55 * scale;
6016 velocity *= velspeed;
6019 if (creature == wolftype) {
6020 if (velspeed > speed * 75 * scale) {
6021 velocity /= velspeed;
6022 velspeed = speed * 75 * scale;
6023 velocity *= velspeed;
6026 velocity.y += gravity * multiplier * 20;
6027 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6028 velspeed = findLength(&velocity);
6029 velocity = flatfacing * velspeed;
6032 if (animTarget == rollanim && targetFrame().label != 6) {
6033 velocity += facing * multiplier * speed * 700 * scale;
6034 velspeed = findLength(&velocity);
6035 if (velspeed > speed * 45 * scale) {
6036 velocity /= velspeed;
6037 velspeed = speed * 45 * scale;
6038 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 == sneakanim || animTarget == walkanim) {
6047 velocity += facing * multiplier * speed * 700 * scale;
6048 velspeed = findLength(&velocity);
6049 if (velspeed > speed * 12 * scale) {
6050 velocity /= velspeed;
6051 velspeed = speed * 12 * 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 == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6061 velocity += facing * multiplier * speed * 700 * scale;
6062 velspeed = findLength(&velocity);
6063 if (velspeed > speed * 2 * scale) {
6064 velocity /= velspeed;
6065 velspeed = speed * 2 * 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 == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
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 * -1;
6088 if (animTarget == fightsidestep) {
6089 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6090 velspeed = findLength(&velocity);
6091 if (velspeed > speed * 12 * scale) {
6092 velocity /= velspeed;
6093 velspeed = speed * 12 * 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 = DoRotation(flatfacing * velspeed, 0, -90, 0);
6102 if (animTarget == staggerbackhighanim) {
6103 coords -= facing * multiplier * speed * 16 * scale;
6106 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6107 coords -= facing * multiplier * speed * 20 * scale;
6111 if (animTarget == backhandspringanim) {
6112 //coords-=facing*multiplier*50*scale;
6113 velocity += facing * multiplier * speed * 700 * scale * -1;
6114 velspeed = findLength(&velocity);
6115 if (velspeed > speed * 50 * scale) {
6116 velocity /= velspeed;
6117 velspeed = speed * 50 * scale;
6118 velocity *= velspeed;
6120 velocity.y += gravity * multiplier * 20;
6121 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6122 velspeed = findLength(&velocity);
6123 velocity = flatfacing * velspeed * -1;
6125 if (animTarget == dodgebackanim) {
6126 //coords-=facing*multiplier*50*scale;
6127 velocity += facing * multiplier * speed * 700 * scale * -1;
6128 velspeed = findLength(&velocity);
6129 if (velspeed > speed * 60 * scale) {
6130 velocity /= velspeed;
6131 velspeed = speed * 60 * 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;
6140 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6141 velspeed = findLength(&velocity);
6144 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6145 velocity.y += gravity * multiplier;
6148 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6149 coords += velocity * multiplier;
6152 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6153 if (isFlip() && targetFrame().label == 7) {
6157 if (animTarget == jumpupanim) {
6159 animTarget = getIdle();
6166 pause_sound(whooshsound);
6167 OPENAL_SetVolume(channels[whooshsound], 0);
6170 if (animTarget == jumpdownanim || isFlip()) {
6174 animTarget = getLanding();
6175 emit_sound_at(landsound, coords, 128.);
6178 addEnvSound(coords);
6183 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6184 coords.y += gravity * multiplier * 2;
6186 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6187 coords.y = terrain.getHeight(coords.x, coords.z);
6191 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)) {
6192 velspeed = findLength(&velocity);
6194 if (velspeed < multiplier * 300 * scale) {
6197 velocity -= velocity / velspeed * multiplier * 300 * scale;
6199 if (velspeed > 5 && (isLanding() || isLandhard())) {
6200 skiddingdelay += multiplier;
6201 if (skiddelay <= 0) {
6202 FootLand(leftfoot, .5);
6203 FootLand(rightfoot, .5);
6212 velspeed = findLength(&velocity);
6214 if (velspeed > 5 && (isLanding() || isLandhard())) {
6215 skiddingdelay += multiplier;
6216 if (skiddelay <= 0) {
6217 FootLand(leftfoot, .5);
6218 FootLand(rightfoot, .5);
6226 if (skiddingdelay < 0) {
6227 skiddingdelay += multiplier;
6229 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6231 if (!onterrain || environment == grassyenvironment) {
6232 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6234 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6238 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6239 terrainnormal = victim->coords - coords;
6240 Normalise(&terrainnormal);
6241 targetyaw = -asin(0 - terrainnormal.x);
6242 targetyaw *= 360 / 6.28;
6243 if (terrainnormal.z < 0) {
6244 targetyaw = 180 - targetyaw;
6246 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6249 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6250 targetyaw = victim->targetyaw;
6252 if (animTarget == rabbittacklinganim) {
6253 coords = victim->coords;
6256 skeleton.oldfree = skeleton.free;
6260 midterrain.x = terrain.size * terrain.scale / 2;
6261 midterrain.z = terrain.size * terrain.scale / 2;
6262 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6264 tempposit = coords - midterrain;
6266 Normalise(&tempposit);
6267 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6268 coords.x = tempposit.x + midterrain.x;
6269 coords.z = tempposit.z + midterrain.z;
6274 * inverse kinematics helper function
6276 void IKHelper(Person* p, float interp)
6278 XYZ point, change, change2;
6279 float heightleft, heightright;
6281 // TODO: implement localToWorld and worldToLocal
6282 // but keep in mind it won't be the same math if player is ragdolled or something
6283 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6284 // then comb through code for places where to use it
6286 // point = localToWorld(jointPos(leftfoot))
6287 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6288 // adjust height of foot
6289 heightleft = terrain.getHeight(point.x, point.z) + .04;
6290 point.y = heightleft;
6291 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6292 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6293 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6294 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6295 // move ankle along with foot
6296 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6297 // average knee pos between old and new pos
6298 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6300 // do same as above for right leg
6301 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6302 heightright = terrain.getHeight(point.x, point.z) + .04;
6303 point.y = heightright;
6304 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6305 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6306 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6307 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6308 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6310 // fix up skeleton now that we've moved body parts?
6311 p->skeleton.DoConstraints(&p->coords, &p->scale);
6318 int Person::DrawSkeleton()
6320 int oldplayerdetail;
6321 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6322 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6332 glAlphaFunc(GL_GREATER, 0.0001);
6334 float terrainheight;
6336 if (!isnormal(yaw)) {
6339 if (!isnormal(tilt)) {
6342 if (!isnormal(tilt2)) {
6345 oldplayerdetail = playerdetail;
6347 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6350 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6353 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6359 if (playerdetail != oldplayerdetail) {
6361 normalsupdatedelay = 0;
6363 static float updatedelaychange;
6364 static float morphness;
6365 static float framemult;
6367 skeleton.FindForwards();
6368 if (howactive == typesittingwall) {
6369 skeleton.specialforward[1] = 0;
6370 skeleton.specialforward[1].z = 1;
6376 static int weaponattachmuscle;
6377 static int weaponrotatemuscle;
6378 static XYZ weaponpoint;
6379 static int start, endthing;
6380 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6381 if (!isSleeping() && !isSitting()) {
6382 // TODO: give these meaningful names
6383 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6384 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6386 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6388 if (creature == wolftype) {
6393 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6394 IKHelper(this, target);
6395 if (creature == wolftype) {
6396 IKHelper(this, target);
6400 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6401 IKHelper(this, 1 - target);
6402 if (creature == wolftype) {
6403 IKHelper(this, 1 - target);
6408 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())) {
6411 targetheadyaw = -targetyaw;
6412 targetheadpitch = 0;
6413 if (Animation::animations[animTarget].attack == 3) {
6414 targetheadyaw += 180;
6417 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6418 skeleton.drawmodel.vertex[i] = 0;
6419 skeleton.drawmodel.vertex[i].y = 999;
6421 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6422 skeleton.drawmodellow.vertex[i] = 0;
6423 skeleton.drawmodellow.vertex[i].y = 999;
6425 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6426 skeleton.drawmodelclothes.vertex[i] = 0;
6427 skeleton.drawmodelclothes.vertex[i].y = 999;
6429 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6430 // convenience renames
6431 const int p1 = skeleton.muscles[i].parent1->label;
6432 const int p2 = skeleton.muscles[i].parent2->label;
6434 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6439 if (p1 == righthand || p2 == righthand) {
6440 morphness = righthandmorphness;
6441 start = righthandmorphstart;
6442 endthing = righthandmorphend;
6444 if (p1 == lefthand || p2 == lefthand) {
6445 morphness = lefthandmorphness;
6446 start = lefthandmorphstart;
6447 endthing = lefthandmorphend;
6449 if (p1 == head || p2 == head) {
6450 morphness = headmorphness;
6451 start = headmorphstart;
6452 endthing = headmorphend;
6454 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6455 morphness = chestmorphness;
6456 start = chestmorphstart;
6457 endthing = chestmorphend;
6459 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6460 morphness = tailmorphness;
6461 start = tailmorphstart;
6462 endthing = tailmorphend;
6465 skeleton.FindRotationMuscle(i, animTarget);
6467 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6468 glMatrixMode(GL_MODELVIEW);
6471 if (!skeleton.free) {
6472 glRotatef(tilt2, 1, 0, 0);
6474 if (!skeleton.free) {
6475 glRotatef(tilt, 0, 0, 1);
6478 glTranslatef(mid.x, mid.y, mid.z);
6480 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6481 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6483 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6484 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6486 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6487 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6489 if (playerdetail || skeleton.free == 3) {
6490 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6491 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6492 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6493 glMatrixMode(GL_MODELVIEW);
6495 if (p1 == abdomen || p2 == abdomen) {
6496 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(1).x,
6497 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(1).y,
6498 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(1).z);
6500 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6501 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(2).x,
6502 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(2).y,
6503 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(2).z);
6505 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6506 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(3).x,
6507 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(3).y,
6508 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(3).z);
6510 if (p1 == head || p2 == head) {
6511 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(0).x,
6512 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(0).y,
6513 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(0).z);
6515 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6516 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6517 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6518 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6522 if (!playerdetail || skeleton.free == 3) {
6523 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6524 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6525 glMatrixMode(GL_MODELVIEW);
6527 if (p1 == abdomen || p2 == abdomen) {
6528 glTranslatef(v0.x * getProportionXYZ(1).x,
6529 v0.y * getProportionXYZ(1).y,
6530 v0.z * getProportionXYZ(1).z);
6532 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6533 glTranslatef(v0.x * getProportionXYZ(2).x,
6534 v0.y * getProportionXYZ(2).y,
6535 v0.z * getProportionXYZ(2).z);
6537 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6538 glTranslatef(v0.x * getProportionXYZ(3).x,
6539 v0.y * getProportionXYZ(3).y,
6540 v0.z * getProportionXYZ(3).z);
6542 if (p1 == head || p2 == head) {
6543 glTranslatef(v0.x * getProportionXYZ(0).x,
6544 v0.y * getProportionXYZ(0).y,
6545 v0.z * getProportionXYZ(0).z);
6548 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6549 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6550 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6551 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6557 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6558 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6560 glMatrixMode(GL_MODELVIEW);
6563 if (!skeleton.free) {
6564 glRotatef(tilt2, 1, 0, 0);
6566 if (!skeleton.free) {
6567 glRotatef(tilt, 0, 0, 1);
6569 glTranslatef(mid.x, mid.y, mid.z);
6570 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6571 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6573 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6574 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6576 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6577 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6579 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6580 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6581 glMatrixMode(GL_MODELVIEW);
6583 if (p1 == abdomen || p2 == abdomen) {
6584 glTranslatef(v0.x * getProportionXYZ(1).x,
6585 v0.y * getProportionXYZ(1).y,
6586 v0.z * getProportionXYZ(1).z);
6588 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6589 glTranslatef(v0.x * getProportionXYZ(2).x,
6590 v0.y * getProportionXYZ(2).y,
6591 v0.z * getProportionXYZ(2).z);
6593 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6594 glTranslatef(v0.x * getProportionXYZ(3).x,
6595 v0.y * getProportionXYZ(3).y,
6596 v0.z * getProportionXYZ(3).z);
6598 if (p1 == head || p2 == head) {
6599 glTranslatef(v0.x * getProportionXYZ(0).x,
6600 v0.y * getProportionXYZ(0).y,
6601 v0.z * getProportionXYZ(0).z);
6603 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6604 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6605 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6606 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6611 updatedelay = 1 + (float)(Random() % 100) / 1000;
6613 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6614 normalsupdatedelay = 1;
6615 if (playerdetail || skeleton.free == 3) {
6616 skeleton.drawmodel.CalculateNormals(0);
6618 if (!playerdetail || skeleton.free == 3) {
6619 skeleton.drawmodellow.CalculateNormals(0);
6621 if (skeleton.clothes) {
6622 skeleton.drawmodelclothes.CalculateNormals(0);
6625 if (playerdetail || skeleton.free == 3) {
6626 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6628 if (!playerdetail || skeleton.free == 3) {
6629 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6631 if (skeleton.clothes) {
6632 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6637 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6638 if (updatedelaychange > -realmultiplier * 30) {
6639 updatedelaychange = -realmultiplier * 30;
6641 if (updatedelaychange > -framemult * 4) {
6642 updatedelaychange = -framemult * 4;
6644 if (skeleton.free == 1) {
6645 updatedelaychange *= 6;
6648 updatedelaychange *= 8;
6650 updatedelay += updatedelaychange;
6652 glMatrixMode(GL_MODELVIEW);
6654 glTranslatef(coords.x, coords.y - .02, coords.z);
6655 if (!skeleton.free) {
6656 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6657 glRotatef(yaw, 0, 1, 0);
6661 glColor4f(.4, 1, .4, 1);
6662 glDisable(GL_LIGHTING);
6663 glDisable(GL_TEXTURE_2D);
6666 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6667 XYZ& v0 = skeleton.drawmodel.vertex[i];
6668 glVertex3f(v0.x, v0.y, v0.z);
6675 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6676 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6677 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6678 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6679 glVertex3f(v0.x, v0.y, v0.z);
6680 glVertex3f(v1.x, v1.y, v1.z);
6681 glVertex3f(v1.x, v1.y, v1.z);
6682 glVertex3f(v2.x, v2.y, v2.z);
6683 glVertex3f(v2.x, v2.y, v2.z);
6684 glVertex3f(v0.x, v0.y, v0.z);
6691 terrainlight = terrain.getLighting(coords.x, coords.z);
6692 distance = distsq(&viewer, &coords);
6693 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6698 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6699 if (terrainheight < 1) {
6702 if (terrainheight > 1.7) {
6703 terrainheight = 1.7;
6706 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6707 glDisable(GL_BLEND);
6708 glAlphaFunc(GL_GREATER, 0.0001);
6709 glEnable(GL_TEXTURE_2D);
6711 glDisable(GL_TEXTURE_2D);
6712 glColor4f(.7, .35, 0, .5);
6714 glEnable(GL_LIGHTING);
6717 if (Tutorial::active && id != 0) {
6718 glColor4f(.7, .7, .7, 0.6);
6720 glEnable(GL_LIGHTING);
6722 if (canattack && cananger) {
6723 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6724 glDisable(GL_TEXTURE_2D);
6725 glColor4f(1, 0, 0, 0.8);
6728 glMatrixMode(GL_TEXTURE);
6730 glTranslatef(0, -smoketex, 0);
6731 glTranslatef(-smoketex, 0, 0);
6735 if (Tutorial::active && (id != 0)) {
6736 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6738 skeleton.drawmodel.draw();
6742 if (!playerdetail) {
6743 if (Tutorial::active && (id != 0)) {
6744 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6746 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6750 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6751 if (Tutorial::active && id != 0) {
6753 glMatrixMode(GL_MODELVIEW);
6754 glEnable(GL_TEXTURE_2D);
6755 glColor4f(.7, .7, .7, 0.6);
6757 glEnable(GL_LIGHTING);
6759 if (canattack && cananger) {
6760 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6761 glDisable(GL_TEXTURE_2D);
6762 glColor4f(1, 0, 0, 0.8);
6765 glMatrixMode(GL_TEXTURE);
6767 glTranslatef(0, -smoketex * .6, 0);
6768 glTranslatef(smoketex * .6, 0, 0);
6771 if (Tutorial::active && (id != 0)) {
6772 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6774 skeleton.drawmodel.draw();
6778 if (!playerdetail) {
6779 if (Tutorial::active && (id != 0)) {
6780 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6782 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6788 if (Tutorial::active && id != 0) {
6790 glMatrixMode(GL_MODELVIEW);
6791 glEnable(GL_TEXTURE_2D);
6793 if (skeleton.clothes) {
6797 skeleton.drawmodelclothes.draw();
6800 skeleton.drawmodelclothes.drawimmediate();
6807 if (num_weapons > 0) {
6808 for (k = 0; k < num_weapons; k++) {
6809 int i = weaponids[k];
6810 if (weaponactive == k) {
6811 if (weapons[i].getType() != staff) {
6812 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6813 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6814 weaponattachmuscle = j;
6817 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6818 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) {
6819 weaponrotatemuscle = j;
6822 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6823 if (creature == wolftype) {
6824 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6827 if (weapons[i].getType() == staff) {
6828 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6829 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6830 weaponattachmuscle = j;
6833 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6834 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) {
6835 weaponrotatemuscle = j;
6838 //weaponpoint=jointPos(rightwrist);
6839 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6840 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6841 XYZ tempnormthing, vec1, vec2;
6842 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6843 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6844 CrossProduct(&vec1, &vec2, &tempnormthing);
6845 Normalise(&tempnormthing);
6846 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
6847 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6851 if (weaponactive != k && weaponstuck != k) {
6852 if (weapons[i].getType() == knife) {
6853 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6855 if (weapons[i].getType() == sword) {
6856 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6858 if (weapons[i].getType() == staff) {
6859 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6861 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6862 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) {
6863 weaponrotatemuscle = j;
6867 if (weaponstuck == k) {
6868 if (weaponstuckwhere == 0) {
6869 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6871 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6873 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6874 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) {
6875 weaponrotatemuscle = j;
6879 if (skeleton.free) {
6880 weapons[i].position = weaponpoint * scale + coords;
6881 weapons[i].bigrotation = 0;
6882 weapons[i].bigtilt = 0;
6883 weapons[i].bigtilt2 = 0;
6885 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;
6886 weapons[i].bigrotation = yaw;
6887 weapons[i].bigtilt = tilt;
6888 weapons[i].bigtilt2 = tilt2;
6890 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6891 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6892 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6893 if (weaponactive == k) {
6894 if (weapons[i].getType() == knife) {
6895 weapons[i].smallrotation = 180;
6896 weapons[i].smallrotation2 = 0;
6897 if (isCrouch() || wasCrouch()) {
6898 weapons[i].smallrotation2 = 20;
6900 if (animTarget == hurtidleanim) {
6901 weapons[i].smallrotation2 = 50;
6903 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6904 XYZ temppoint1, temppoint2;
6907 temppoint1 = jointPos(righthand);
6908 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6909 distance = findDistance(&temppoint1, &temppoint2);
6910 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6911 weapons[i].rotation2 *= 360 / 6.28;
6914 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6915 weapons[i].rotation1 *= 360 / 6.28;
6916 weapons[i].rotation3 = 0;
6917 weapons[i].smallrotation = -90;
6918 weapons[i].smallrotation2 = 0;
6919 if (temppoint1.x > temppoint2.x) {
6920 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6923 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6924 XYZ temppoint1, temppoint2;
6927 temppoint1 = jointPos(righthand);
6928 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6929 distance = findDistance(&temppoint1, &temppoint2);
6930 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6931 weapons[i].rotation2 *= 360 / 6.28;
6934 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6935 weapons[i].rotation1 *= 360 / 6.28;
6936 weapons[i].rotation3 = 0;
6937 weapons[i].smallrotation = 90;
6938 weapons[i].smallrotation2 = 0;
6939 if (temppoint1.x > temppoint2.x) {
6940 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6943 if (animTarget == knifethrowanim) {
6944 weapons[i].smallrotation = 90;
6945 //weapons[i].smallrotation2=-90;
6946 weapons[i].smallrotation2 = 0;
6947 weapons[i].rotation1 = 0;
6948 weapons[i].rotation2 = 0;
6949 weapons[i].rotation3 = 0;
6951 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6952 weapons[i].smallrotation = -90;
6953 weapons[i].rotation1 = 0;
6954 weapons[i].rotation2 = 0;
6955 weapons[i].rotation3 = 0;
6958 if (weapons[i].getType() == sword) {
6959 weapons[i].smallrotation = 0;
6960 weapons[i].smallrotation2 = 0;
6961 if (animTarget == knifethrowanim) {
6962 weapons[i].smallrotation = -90;
6963 weapons[i].smallrotation2 = 0;
6964 weapons[i].rotation1 = 0;
6965 weapons[i].rotation2 = 0;
6966 weapons[i].rotation3 = 0;
6968 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)) {
6969 XYZ temppoint1, temppoint2;
6972 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6973 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6974 distance = findDistance(&temppoint1, &temppoint2);
6975 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6976 weapons[i].rotation2 *= 360 / 6.28;
6979 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6980 weapons[i].rotation1 *= 360 / 6.28;
6981 weapons[i].rotation3 = 0;
6982 weapons[i].smallrotation = 90;
6983 weapons[i].smallrotation2 = 0;
6984 if (temppoint1.x > temppoint2.x) {
6985 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6989 if (weapons[i].getType() == staff) {
6990 weapons[i].smallrotation = 100;
6991 weapons[i].smallrotation2 = 0;
6992 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6993 XYZ temppoint1, temppoint2;
6996 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6997 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6998 distance = findDistance(&temppoint1, &temppoint2);
6999 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7000 weapons[i].rotation2 *= 360 / 6.28;
7003 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7004 weapons[i].rotation1 *= 360 / 6.28;
7005 weapons[i].rotation3 = 0;
7006 weapons[i].smallrotation = 90;
7007 weapons[i].smallrotation2 = 0;
7008 if (temppoint1.x > temppoint2.x) {
7009 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7014 if (weaponactive != k && weaponstuck != k) {
7015 if (weapons[i].getType() == knife) {
7016 weapons[i].smallrotation = -70;
7017 weapons[i].smallrotation2 = 10;
7019 if (weapons[i].getType() == sword) {
7020 weapons[i].smallrotation = -100;
7021 weapons[i].smallrotation2 = -8;
7023 if (weapons[i].getType() == staff) {
7024 weapons[i].smallrotation = -100;
7025 weapons[i].smallrotation2 = -8;
7028 if (weaponstuck == k) {
7029 if (weaponstuckwhere == 0) {
7030 weapons[i].smallrotation = 180;
7032 weapons[i].smallrotation = 0;
7034 weapons[i].smallrotation2 = 10;
7041 if (skeleton.free) {
7044 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7047 if (animCurrent != animTarget) {
7050 if (skeleton.free == 2) {
7059 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7061 static float distance;
7062 static float olddistance;
7063 static int intersecting;
7064 static int firstintersecting;
7067 static XYZ start, end;
7068 static float slopethreshold = -.4;
7070 firstintersecting = -1;
7074 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7078 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7080 for (int i = 0; i < 4; i++) {
7081 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7082 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7084 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)));
7085 if (distance < radius) {
7086 point = *p1 - model->Triangles[j].facenormal * distance;
7087 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]])) {
7090 if (!intersecting) {
7091 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7092 &model->vertex[model->Triangles[j].vertex[1]],
7095 if (!intersecting) {
7096 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7097 &model->vertex[model->Triangles[j].vertex[2]],
7100 if (!intersecting) {
7101 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7102 &model->vertex[model->Triangles[j].vertex[2]],
7106 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7110 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)) {
7111 p1->y = point.y + radius;
7112 if ((animTarget == jumpdownanim || isFlip())) {
7113 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7117 if (animTarget == jumpupanim) {
7119 animTarget = getIdle();
7126 pause_sound(whooshsound);
7127 OPENAL_SetVolume(channels[whooshsound], 0);
7130 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7134 animTarget = getLanding();
7135 emit_sound_at(landsound, coords, 128.);
7138 addEnvSound(coords);
7145 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7146 olddistance = distance;
7147 firstintersecting = j;
7152 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7153 if (model->Triangles[j].facenormal.y > slopethreshold) {
7156 start.y -= radius / 4;
7157 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7158 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7159 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7160 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)));
7161 if (distance < radius * .5) {
7162 point = start - model->Triangles[j].facenormal * distance;
7163 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7166 if (!intersecting) {
7167 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7169 if (!intersecting) {
7170 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7172 if (!intersecting) {
7173 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7176 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7177 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7179 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;
7180 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7184 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7187 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7188 olddistance = distance;
7189 firstintersecting = j;
7196 *p = DoRotation(*p, 0, *rotate, 0);
7200 *p1 = DoRotation(*p1, 0, *rotate, 0);
7203 return firstintersecting;
7206 int findPathDist(int start, int end)
7211 unsigned int smallestcount = 1000;
7212 for (char i = 0; i < 50; i++) {
7213 unsigned int count = 0;
7218 while (last != end && count < 30) {
7220 for (int j = 0; j < Game::numpathpoints; j++) {
7221 if (j != last && j != last2 && j != last3 && j != last4) {
7223 if (Game::numpathpointconnect[j]) {
7224 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7225 if (Game::pathpointconnect[j][k] == last) {
7231 if (Game::numpathpointconnect[last]) {
7232 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7233 if (Game::pathpointconnect[last][k] == j) {
7240 if (closest == -1 || Random() % 2 == 0) {
7252 if (count < smallestcount) {
7253 smallestcount = count;
7256 return smallestcount;
7259 void Person::takeWeapon(int weaponId)
7262 weapons[weaponId].owner = id;
7263 if (num_weapons > 0) {
7264 weaponids[num_weapons] = weaponids[0];
7267 weaponids[0] = weaponId;
7270 void Person::addClothes()
7272 if (numclothes > 0) {
7273 for (int i = 0; i < numclothes; i++) {
7280 bool Person::addClothes(const int& clothesId)
7283 const std::string fileName = clothes[clothesId];
7285 GLubyte* array = &skeleton.skinText[0];
7289 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7294 float tintr = clothestintr[clothesId];
7295 float tintg = clothestintg[clothesId];
7296 float tintb = clothestintb[clothesId];
7318 int bytesPerPixel = texture.bpp / 8;
7322 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7323 if (bytesPerPixel == 3) {
7325 } else if ((i + 1) % 4 == 0) {
7326 alphanum = texture.data[i];
7328 if ((i + 1) % 4 || bytesPerPixel == 3) {
7330 texture.data[i] *= tintr;
7333 texture.data[i] *= tintg;
7336 texture.data[i] *= tintb;
7338 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7350 if (aitype != playercontrolled && !Dialog::inDialog()) {
7352 //disable movement in editor
7353 if (Game::editorenabled) {
7358 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7359 Person::players[0]->coords.y > coords.y + 2 &&
7360 !Person::players[0]->onterrain) {
7365 if (aitype == pathfindtype) {
7366 if (finalpathfindpoint == -1) {
7367 float closestdistance;
7368 float tempdist = 0.0f;
7372 closestdistance = -1;
7373 for (int j = 0; j < Game::numpathpoints; j++) {
7374 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7375 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7377 finaltarget = Game::pathpoint[j];
7380 finalpathfindpoint = closest;
7381 for (int j = 0; j < Game::numpathpoints; j++) {
7382 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7383 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7384 if (sq(tempdist) < closestdistance) {
7385 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7386 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7387 closestdistance = sq(tempdist);
7389 finaltarget = colpoint;
7394 finalpathfindpoint = closest;
7396 if (targetpathfindpoint == -1) {
7397 float closestdistance;
7398 float tempdist = 0.0f;
7402 closestdistance = -1;
7403 if (lastpathfindpoint == -1) {
7404 for (int j = 0; j < Game::numpathpoints; j++) {
7405 if (j != lastpathfindpoint) {
7406 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7407 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7412 targetpathfindpoint = closest;
7413 for (int j = 0; j < Game::numpathpoints; j++) {
7414 if (j != lastpathfindpoint) {
7415 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7416 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7417 if (sq(tempdist) < closestdistance) {
7418 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7419 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7420 closestdistance = sq(tempdist);
7427 targetpathfindpoint = closest;
7429 for (int j = 0; j < Game::numpathpoints; j++) {
7430 if (j != lastpathfindpoint &&
7431 j != lastpathfindpoint2 &&
7432 j != lastpathfindpoint3 &&
7433 j != lastpathfindpoint4) {
7435 if (Game::numpathpointconnect[j]) {
7436 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7437 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7443 if (Game::numpathpointconnect[lastpathfindpoint]) {
7444 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7445 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7452 tempdist = findPathDist(j, finalpathfindpoint);
7453 if (closest == -1 || tempdist < closestdistance) {
7454 closestdistance = tempdist;
7460 targetpathfindpoint = closest;
7463 losupdatedelay -= multiplier;
7465 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7466 lookyaw = targetyaw;
7468 //reached target point
7469 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7470 lastpathfindpoint4 = lastpathfindpoint3;
7471 lastpathfindpoint3 = lastpathfindpoint2;
7472 lastpathfindpoint2 = lastpathfindpoint;
7473 lastpathfindpoint = targetpathfindpoint;
7474 if (lastpathfindpoint2 == -1) {
7475 lastpathfindpoint2 = lastpathfindpoint;
7477 if (lastpathfindpoint3 == -1) {
7478 lastpathfindpoint3 = lastpathfindpoint2;
7480 if (lastpathfindpoint4 == -1) {
7481 lastpathfindpoint4 = lastpathfindpoint3;
7483 targetpathfindpoint = -1;
7485 if (distsqflat(&coords, &finalfinaltarget) <
7486 distsqflat(&coords, &finaltarget) ||
7487 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7488 lastpathfindpoint == finalpathfindpoint) {
7489 aitype = passivetype;
7500 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7501 targetyaw += 90 * (whichdirection * 2 - 1);
7504 if (collided < 1 || animTarget != jumpupanim) {
7507 if ((collided > .8 && jumppower >= 5)) {
7511 if ((!Tutorial::active || cananger) &&
7513 !Person::players[0]->dead &&
7514 distsq(&coords, &Person::players[0]->coords) < 400 &&
7516 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7517 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7518 !Game::editorenabled &&
7519 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7520 aitype = attacktypecutoff;
7522 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7523 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7524 !Game::editorenabled) {
7525 aitype = attacktypecutoff;
7528 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7529 losupdatedelay = .2;
7530 for (unsigned j = 0; j < Person::players.size(); j++) {
7531 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7532 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7533 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7534 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7535 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7536 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) ||
7537 (Person::players[j]->animTarget == hanganim &&
7538 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7539 aitype = searchtype;
7541 lastseen = Person::players[j]->coords;
7552 if (aitype == attacktypecutoff && Game::musictype != 2) {
7553 if (creature != wolftype) {
7560 if (aitype != passivetype && Game::leveltime > .5) {
7561 howactive = typeactive;
7564 if (aitype == passivetype) {
7565 aiupdatedelay -= multiplier;
7566 losupdatedelay -= multiplier;
7567 lastseentime += multiplier;
7568 pausetime -= multiplier;
7569 if (lastseentime > 1) {
7573 if (aiupdatedelay < 0) {
7574 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7575 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7576 lookyaw = targetyaw;
7577 aiupdatedelay = .05;
7579 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7580 if (waypointtype[waypoint] == wppause) {
7584 if (waypoint > numwaypoints - 1) {
7590 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7602 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7603 if (!avoidsomething) {
7604 targetyaw += 90 * (whichdirection * 2 - 1);
7606 XYZ leftpos, rightpos;
7607 float leftdist, rightdist;
7608 leftpos = coords + DoRotation(facing, 0, 90, 0);
7609 rightpos = coords - DoRotation(facing, 0, 90, 0);
7610 leftdist = distsq(&leftpos, &avoidwhere);
7611 rightdist = distsq(&rightpos, &avoidwhere);
7612 if (leftdist < rightdist) {
7620 if (collided < 1 || animTarget != jumpupanim) {
7623 if ((collided > .8 && jumppower >= 5)) {
7628 if (!Game::editorenabled) {
7629 if (howactive <= typesleeping) {
7630 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7631 for (int j = 0; j < numenvsounds; j++) {
7632 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7633 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7634 aitype = attacktypecutoff;
7640 if (aitype != passivetype) {
7641 if (howactive == typesleeping) {
7642 setTargetAnimation(getupfromfrontanim);
7644 howactive = typeactive;
7648 if (howactive < typesleeping &&
7649 ((!Tutorial::active || cananger) && hostile) &&
7650 !Person::players[0]->dead &&
7651 distsq(&coords, &Person::players[0]->coords) < 400 &&
7653 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7654 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7655 aitype = attacktypecutoff;
7657 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7658 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7659 aitype = attacktypecutoff;
7663 if (creature == wolftype) {
7665 for (unsigned j = 0; j < Person::players.size(); j++) {
7666 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7667 float smelldistance = 50;
7668 if (j == 0 && Person::players[j]->num_weapons > 0) {
7669 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7670 smelldistance = 100;
7672 if (Person::players[j]->num_weapons == 2) {
7673 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7674 smelldistance = 100;
7679 smelldistance = 100;
7681 windsmell = windvector;
7682 Normalise(&windsmell);
7683 windsmell = windsmell * 2 + Person::players[j]->coords;
7684 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7685 aitype = attacktypecutoff;
7691 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7692 losupdatedelay = .2;
7693 for (unsigned j = 0; j < Person::players.size(); j++) {
7694 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7695 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7696 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7697 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7698 if ((-1 == Object::checkcollide(
7699 DoRotation(jointPos(head), 0, yaw, 0) *
7702 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7703 Person::players[j]->scale +
7704 Person::players[j]->coords) &&
7705 !Person::players[j]->isWallJump()) ||
7706 (Person::players[j]->animTarget == hanganim &&
7707 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7709 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7718 if (lastseentime <= 0) {
7719 aitype = searchtype;
7721 lastseen = Person::players[j]->coords;
7729 if (aitype == attacktypecutoff && Game::musictype != 2) {
7730 if (creature != wolftype) {
7734 if (creature == wolftype) {
7744 if (aitype == searchtype) {
7745 aiupdatedelay -= multiplier;
7746 losupdatedelay -= multiplier;
7748 lastseentime -= multiplier;
7750 lastchecktime -= multiplier;
7752 if (isRun() && !onground) {
7753 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7754 XYZ test2 = coords + facing;
7756 XYZ test = coords + facing;
7758 j = Object::checkcollide(test2, test, laststanding);
7760 j = Object::checkcollide(test2, test);
7764 setTargetAnimation(getStop());
7767 //aitype=passivetype;
7768 aitype = pathfindtype;
7769 finalfinaltarget = waypoints[waypoint];
7770 finalpathfindpoint = -1;
7771 targetpathfindpoint = -1;
7772 lastpathfindpoint = -1;
7773 lastpathfindpoint2 = -1;
7774 lastpathfindpoint3 = -1;
7775 lastpathfindpoint4 = -1;
7781 //check out last seen location
7782 if (aiupdatedelay < 0) {
7783 targetyaw = roughDirectionTo(coords, lastseen);
7784 lookyaw = targetyaw;
7785 aiupdatedelay = .05;
7788 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7791 lastseen.x += (float(Random() % 100) - 50) / 25;
7792 lastseen.z += (float(Random() % 100) - 50) / 25;
7803 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7804 if (!avoidsomething) {
7805 targetyaw += 90 * (whichdirection * 2 - 1);
7807 XYZ leftpos, rightpos;
7808 float leftdist, rightdist;
7809 leftpos = coords + DoRotation(facing, 0, 90, 0);
7810 rightpos = coords - DoRotation(facing, 0, 90, 0);
7811 leftdist = distsq(&leftpos, &avoidwhere);
7812 rightdist = distsq(&rightpos, &avoidwhere);
7813 if (leftdist < rightdist) {
7821 if (collided < 1 || animTarget != jumpupanim) {
7824 if ((collided > .8 && jumppower >= 5)) {
7828 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
7829 for (int k = 0; k < numenvsounds; k++) {
7830 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7831 aitype = attacktypecutoff;
7836 if (!Person::players[0]->dead &&
7837 losupdatedelay < 0 &&
7838 !Game::editorenabled &&
7840 ((!Tutorial::active || cananger) && hostile)) {
7841 losupdatedelay = .2;
7842 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7843 aitype = attacktypecutoff;
7846 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
7847 //TODO: factor out canSeePlayer()
7848 if (distsq(&coords, &Person::players[0]->coords) < 400) {
7849 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
7850 if ((Object::checkcollide(
7851 DoRotation(jointPos(head), 0, yaw, 0) *
7854 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7855 Person::players[0]->scale +
7856 Person::players[0]->coords) == -1) ||
7857 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7858 /* //TODO: changed j to 0 on a whim, make sure this is correct
7859 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7860 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7862 aitype = attacktypecutoff;
7870 if (lastseentime < 0) {
7871 //aitype=passivetype;
7873 aitype = pathfindtype;
7874 finalfinaltarget = waypoints[waypoint];
7875 finalpathfindpoint = -1;
7876 targetpathfindpoint = -1;
7877 lastpathfindpoint = -1;
7878 lastpathfindpoint2 = -1;
7879 lastpathfindpoint3 = -1;
7880 lastpathfindpoint4 = -1;
7884 if (aitype != gethelptype) {
7888 //get help from buddies
7889 if (aitype == gethelptype) {
7890 runninghowlong += multiplier;
7891 aiupdatedelay -= multiplier;
7893 if (aiupdatedelay < 0 || ally == 0) {
7897 //TODO: factor out closest search somehow
7900 float closestdist = -1;
7901 for (unsigned k = 0; k < Person::players.size(); k++) {
7902 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7903 (Person::players[k]->howactive < typedead1) &&
7904 !Person::players[k]->skeleton.free &&
7905 (Person::players[k]->aitype == passivetype)) {
7906 float distance = distsq(&coords, &Person::players[k]->coords);
7907 if (closestdist == -1 || distance < closestdist) {
7908 closestdist = distance;
7913 if (closest != -1) {
7918 lastseen = Person::players[0]->coords;
7924 XYZ facing = coords;
7925 XYZ flatfacing = Person::players[ally]->coords;
7926 facing.y += jointPos(head).y * scale;
7927 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7928 if (-1 != Object::checkcollide(facing, flatfacing)) {
7932 //no available ally, run back to player
7934 Person::players[ally]->skeleton.free ||
7935 Person::players[ally]->aitype != passivetype ||
7936 lastseentime <= 0) {
7937 aitype = searchtype;
7943 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7944 lookyaw = targetyaw;
7945 aiupdatedelay = .05;
7948 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7949 aitype = searchtype;
7951 Person::players[ally]->aitype = searchtype;
7952 if (Person::players[ally]->lastseentime < lastseentime) {
7953 Person::players[ally]->lastseen = lastseen;
7954 Person::players[ally]->lastseentime = lastseentime;
7955 Person::players[ally]->lastchecktime = lastchecktime;
7959 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7960 if (!avoidsomething) {
7961 targetyaw += 90 * (whichdirection * 2 - 1);
7963 XYZ leftpos, rightpos;
7964 float leftdist, rightdist;
7965 leftpos = coords + DoRotation(facing, 0, 90, 0);
7966 rightpos = coords - DoRotation(facing, 0, 90, 0);
7967 leftdist = distsq(&leftpos, &avoidwhere);
7968 rightdist = distsq(&rightpos, &avoidwhere);
7969 if (leftdist < rightdist) {
7984 if (collided < 1 || animTarget != jumpupanim) {
7987 if (collided > .8 && jumppower >= 5) {
7992 //retreiving a weapon on the ground
7993 if (aitype == getweapontype) {
7994 aiupdatedelay -= multiplier;
7995 lastchecktime -= multiplier;
7997 if (aiupdatedelay < 0) {
8003 float closestdist = -1;
8004 for (unsigned k = 0; k < weapons.size(); k++) {
8005 if (weapons[k].owner == -1) {
8006 float distance = distsq(&coords, &weapons[k].position);
8007 if (closestdist == -1 || distance < closestdist) {
8008 closestdist = distance;
8013 if (closest != -1) {
8022 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8023 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8024 aitype = attacktypecutoff;
8028 if (!Person::players[0]->dead) {
8030 if (weapons[ally].owner != -1 ||
8031 distsq(&coords, &weapons[ally].position) > 16) {
8032 aitype = attacktypecutoff;
8035 //TODO: factor these out as moveToward()
8036 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8037 lookyaw = targetyaw;
8038 aiupdatedelay = .05;
8041 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8042 if (!avoidsomething) {
8043 targetyaw += 90 * (whichdirection * 2 - 1);
8045 XYZ leftpos, rightpos;
8046 float leftdist, rightdist;
8047 leftpos = coords + DoRotation(facing, 0, 90, 0);
8048 rightpos = coords - DoRotation(facing, 0, 90, 0);
8049 leftdist = distsq(&leftpos, &avoidwhere);
8050 rightdist = distsq(&rightpos, &avoidwhere);
8051 if (leftdist < rightdist) {
8067 if (animTarget != crouchremoveknifeanim &&
8068 animTarget != removeknifeanim) {
8069 throwtogglekeydown = 0;
8073 if (collided < 1 || animTarget != jumpupanim) {
8076 if ((collided > .8 && jumppower >= 5)) {
8081 if (aitype == attacktypecutoff) {
8082 aiupdatedelay -= multiplier;
8083 //dodge or reverse rabbit kicks, knife throws, flips
8084 if (damage < damagetolerance * 2 / 3) {
8085 if ((Person::players[0]->animTarget == rabbitkickanim ||
8086 Person::players[0]->animTarget == knifethrowanim ||
8087 (Person::players[0]->isFlip() &&
8088 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8089 !Person::players[0]->skeleton.free &&
8090 (aiupdatedelay < .1)) {
8095 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8096 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8097 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8098 if (abs(Random() % 2) == 0) {
8099 setTargetAnimation(backhandspringanim);
8101 setTargetAnimation(rollanim);
8103 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8106 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8107 setTargetAnimation(flipanim);
8112 aiupdatedelay = .02;
8115 //get confused by flips
8116 if (Person::players[0]->isFlip() &&
8117 !Person::players[0]->skeleton.free &&
8118 Person::players[0]->animTarget != walljumprightkickanim &&
8119 Person::players[0]->animTarget != walljumpleftkickanim) {
8120 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8121 if ((1 - damage / damagetolerance) > .5) {
8126 //go for weapon on the ground
8127 if (wentforweapon < 3) {
8128 for (unsigned k = 0; k < weapons.size(); k++) {
8129 if (creature != wolftype) {
8130 if (num_weapons == 0 &&
8131 weapons[k].owner == -1 &&
8132 weapons[k].velocity.x == 0 &&
8133 weapons[k].velocity.z == 0 &&
8134 weapons[k].velocity.y == 0) {
8135 if (distsq(&coords, &weapons[k].position) < 16) {
8138 aitype = getweapontype;
8145 //dodge/reverse walljump kicks
8146 if (damage < damagetolerance / 2) {
8147 if (Animation::animations[animTarget].height != highheight) {
8148 if (damage < damagetolerance * .5 &&
8149 ((Person::players[0]->animTarget == walljumprightkickanim ||
8150 Person::players[0]->animTarget == walljumpleftkickanim) &&
8151 ((aiupdatedelay < .15 &&
8153 (aiupdatedelay < .08 &&
8154 difficulty != 2)))) {
8159 //walked off a ledge (?)
8160 if (isRun() && !onground) {
8161 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8162 XYZ test2 = coords + facing;
8164 XYZ test = coords + facing;
8166 j = Object::checkcollide(test2, test, laststanding);
8168 j = Object::checkcollide(test2, test);
8172 setTargetAnimation(getStop());
8175 aitype = pathfindtype;
8176 finalfinaltarget = waypoints[waypoint];
8177 finalpathfindpoint = -1;
8178 targetpathfindpoint = -1;
8179 lastpathfindpoint = -1;
8180 lastpathfindpoint2 = -1;
8181 lastpathfindpoint3 = -1;
8182 lastpathfindpoint4 = -1;
8188 //lose sight of player in the air (?)
8189 if (Person::players[0]->coords.y > coords.y + 5 &&
8190 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8191 !Person::players[0]->onterrain) {
8192 aitype = pathfindtype;
8193 finalfinaltarget = waypoints[waypoint];
8194 finalpathfindpoint = -1;
8195 targetpathfindpoint = -1;
8196 lastpathfindpoint = -1;
8197 lastpathfindpoint2 = -1;
8198 lastpathfindpoint3 = -1;
8199 lastpathfindpoint4 = -1;
8201 //it's time to think (?)
8202 if (aiupdatedelay < 0 &&
8203 !Animation::animations[animTarget].attack &&
8204 animTarget != staggerbackhighanim &&
8205 animTarget != staggerbackhardanim &&
8206 animTarget != backhandspringanim &&
8207 animTarget != dodgebackanim) {
8209 if (weaponactive == -1 && num_weapons > 0) {
8210 drawkeydown = Random() % 2;
8214 rabbitkickenabled = Random() % 2;
8216 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8217 XYZ targetpoint = Person::players[0]->coords;
8218 float vellength = findLength(&velocity);
8219 if (vellength != 0 &&
8220 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8221 targetpoint += Person::players[0]->velocity *
8222 findDistance(&Person::players[0]->coords, &coords) / vellength;
8224 targetyaw = roughDirectionTo(coords, targetpoint);
8225 lookyaw = targetyaw;
8226 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8228 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8230 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8231 distsq(&coords, &Person::players[0]->coords) < 9) &&
8232 Person::players[0]->weaponactive != -1) {
8234 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8239 //chill out around the corpse
8240 if (Person::players[0]->dead) {
8242 if (Random() % 10 == 0) {
8245 if (Random() % 100 == 0) {
8246 aitype = pathfindtype;
8247 finalfinaltarget = waypoints[waypoint];
8248 finalpathfindpoint = -1;
8249 targetpathfindpoint = -1;
8250 lastpathfindpoint = -1;
8251 lastpathfindpoint2 = -1;
8252 lastpathfindpoint3 = -1;
8253 lastpathfindpoint4 = -1;
8262 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8263 targetyaw += 90 * (whichdirection * 2 - 1);
8266 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8271 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8276 if (aitype != playercontrolled &&
8281 for (unsigned j = 0; j < Person::players.size(); j++) {
8282 if (j != id && !Person::players[j]->skeleton.free &&
8283 Person::players[j]->hasvictim &&
8284 (Tutorial::active && reversaltrain ||
8285 Random() % 2 == 0 && difficulty == 2 ||
8286 Random() % 4 == 0 && difficulty == 1 ||
8287 Random() % 8 == 0 && difficulty == 0 ||
8288 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8289 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8290 (Random() % 2 == 0 || difficulty == 2) ||
8291 (isIdle() || isRun()) &&
8292 Person::players[j]->weaponactive != -1 ||
8293 Person::players[j]->animTarget == swordslashanim &&
8294 weaponactive != -1 ||
8295 Person::players[j]->animTarget == staffhitanim ||
8296 Person::players[j]->animTarget == staffspinhitanim)) {
8297 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8298 Person::players[j]->victim == Person::players[id] &&
8299 (Person::players[j]->animTarget == sweepanim ||
8300 Person::players[j]->animTarget == spinkickanim ||
8301 Person::players[j]->animTarget == staffhitanim ||
8302 Person::players[j]->animTarget == staffspinhitanim ||
8303 Person::players[j]->animTarget == winduppunchanim ||
8304 Person::players[j]->animTarget == upunchanim ||
8305 Person::players[j]->animTarget == wolfslapanim ||
8306 Person::players[j]->animTarget == knifeslashstartanim ||
8307 Person::players[j]->animTarget == swordslashanim &&
8308 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8309 weaponactive != -1))) {
8319 Person::players[target]->Reverse();
8326 if (collided > .8 && jumppower >= 5 ||
8327 distsq(&coords, &Person::players[0]->coords) > 400 &&
8329 creature == rabbittype) {
8332 //TODO: why are we controlling the human?
8333 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8334 Person::players[0]->jumpkeydown = 0;
8336 if (Person::players[0]->animTarget == jumpdownanim &&
8337 distsq(&Person::players[0]->coords, &coords) < 40) {
8344 if (Tutorial::active) {
8350 XYZ facing = coords;
8351 XYZ flatfacing = Person::players[0]->coords;
8352 facing.y += jointPos(head).y * scale;
8353 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8354 if (occluded >= 2) {
8355 if (-1 != Object::checkcollide(facing, flatfacing)) {
8359 if (lastseentime <= 0 &&
8360 (creature != wolftype ||
8361 weaponstuck == -1)) {
8362 aitype = searchtype;
8364 lastseen = Person::players[0]->coords;
8373 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8374 (aitype == attacktypecutoff ||
8375 aitype == searchtype)) {
8376 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8377 XYZ test = Person::players[0]->coords;
8379 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8385 if (aitype == passivetype && !(numwaypoints > 1) ||
8387 pause && damage > superpermanentdamage) {
8406 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8407 facing = flatfacing;
8409 if (aitype == attacktypecutoff) {
8410 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8411 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8412 } else if (howactive >= typesleeping) {
8413 targetheadyaw = targetyaw;
8414 targetheadpitch = 0;
8416 if (interestdelay <= 0) {
8417 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8418 headtarget = coords;
8419 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8420 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8421 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8422 headtarget += facing * 1.5;
8424 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8425 targetheadpitch = pitchTo(coords, headtarget);