2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decalstoggle;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern float smoketex;
59 extern bool reversaltrain;
60 extern bool canattack;
62 extern float damagedealt;
64 extern float hostiletime;
66 extern bool gamestarted;
68 extern XYZ envsound[30];
69 extern float envsoundvol[30];
70 extern int numenvsounds;
71 extern float envsoundlife[30];
73 extern XYZ windvector;
75 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
80 , animCurrent(bounceidleanim)
81 , animTarget(bounceidleanim)
88 , howactive(typeactive)
90 , superruntoggle(false)
124 , rabbitkickenabled(false)
138 , superpermanentdamage(0)
181 , normalsupdatedelay(0)
185 , forwardkeydown(false)
186 , forwardstogglekeydown(false)
187 , rightkeydown(false)
191 , jumptogglekeydown(false)
192 , crouchkeydown(false)
193 , crouchtogglekeydown(false)
195 , drawtogglekeydown(false)
196 , throwkeydown(false)
197 , throwtogglekeydown(false)
198 , attackkeydown(false)
220 , whichdirection(false)
221 , whichdirectiondelay(0)
222 , avoidsomething(false)
232 , lefthandmorphness(0)
233 , righthandmorphness(0)
237 , targetlefthandmorphness(0)
238 , targetrighthandmorphness(0)
239 , targetheadmorphness(1)
240 , targetchestmorphness(0)
241 , targettailmorphness(0)
242 , lefthandmorphstart(0)
243 , lefthandmorphend(0)
244 , righthandmorphstart(0)
245 , righthandmorphend(0)
255 , highreversaldelay(0)
256 , lowreversaldelay(0)
305 , weaponstuckwhere(0)
318 , finalpathfindpoint(0)
319 , targetpathfindpoint(0)
320 , lastpathfindpoint(0)
321 , lastpathfindpoint2(0)
322 , lastpathfindpoint3(0)
323 , lastpathfindpoint4(0)
343 , neckspurtparticledelay(0)
348 , rabbitkickragdoll(false)
356 setProportions(1, 1, 1, 1);
359 /* Read a person in tfile. Throws an error if it’s not valid */
360 Person::Person(FILE* tfile, int mapvers, unsigned i)
364 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
366 funpackf(tfile, "Bi", &howactive);
368 howactive = typeactive;
371 funpackf(tfile, "Bf", &scale);
376 funpackf(tfile, "Bb", &immobile);
381 funpackf(tfile, "Bf", &yaw);
386 if (num_weapons < 0 || num_weapons > 5) {
387 throw InvalidPersonException();
389 if (num_weapons > 0 && num_weapons < 5) {
390 for (int j = 0; j < num_weapons; j++) {
391 weaponids[j] = weapons.size();
393 funpackf(tfile, "Bi", &type);
394 weapons.push_back(Weapon(type, id));
397 funpackf(tfile, "Bi", &numwaypoints);
398 for (int j = 0; j < numwaypoints; j++) {
399 funpackf(tfile, "Bf", &waypoints[j].x);
400 funpackf(tfile, "Bf", &waypoints[j].y);
401 funpackf(tfile, "Bf", &waypoints[j].z);
403 funpackf(tfile, "Bi", &waypointtype[j]);
405 waypointtype[j] = wpkeepwalking;
409 funpackf(tfile, "Bi", &waypoint);
410 if (waypoint > (numwaypoints - 1)) {
414 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
415 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
416 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
417 funpackf(tfile, "Bf Bf", &power, &speedmult);
420 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
422 setProportions(1, 1, 1, 1);
425 funpackf(tfile, "Bi", &numclothes);
426 for (int k = 0; k < numclothes; k++) {
428 funpackf(tfile, "Bi", &templength);
429 for (int l = 0; l < templength; l++) {
430 funpackf(tfile, "Bb", &clothes[k][l]);
432 clothes[k][templength] = '\0';
433 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
438 if (creature == wolftype) {
439 damagetolerance = 300;
443 if (creature == wolftype) {
451 realoldcoords = coords;
454 void Person::skeletonLoad(bool clothes)
458 PersonType::types[creature].figureFileName,
459 PersonType::types[creature].lowFigureFileName,
460 PersonType::types[creature].clothesFileName,
461 PersonType::types[creature].modelFileNames[0],
462 PersonType::types[creature].modelFileNames[1],
463 PersonType::types[creature].modelFileNames[2],
464 PersonType::types[creature].modelFileNames[3],
465 PersonType::types[creature].modelFileNames[4],
466 PersonType::types[creature].modelFileNames[5],
467 PersonType::types[creature].modelFileNames[6],
468 PersonType::types[creature].lowModelFileName,
469 PersonType::types[creature].modelClothesFileName,
472 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
475 void Person::setProportions(float head, float body, float arms, float legs)
477 proportions[0] = head;
478 proportions[1] = body;
479 proportions[2] = arms;
480 proportions[3] = legs;
483 float Person::getProportion(int part) const
485 return proportions[part];
488 XYZ Person::getProportionXYZ(int part) const
490 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
500 * GameTick/doPlayerCollisions
502 void Person::CheckKick()
504 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
508 if (Animation::animations[victim->animTarget].height != lowheight) {
509 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
510 XYZ relative = velocity;
512 Normalise(&relative);
516 if (!Tutorial::active) {
517 emit_sound_at(heavyimpactsound, victim->coords);
520 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
521 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
524 victim->DoDamage(100 * damagemult / victim->protectionhigh);
531 animTarget = backflipanim;
533 velocity = facing * -10;
537 resume_stream(whooshsound);
540 award_bonus(id, cannon);
541 } else if (victim->isCrouch()) {
542 animTarget = rabbitkickreversedanim;
543 animCurrent = rabbitkickreversedanim;
544 victim->animCurrent = rabbitkickreversalanim;
545 victim->animTarget = rabbitkickreversalanim;
551 victim->oldcoords = victim->coords;
552 coords = victim->coords;
553 victim->targetyaw = targetyaw;
554 victim->victim = this->shared_from_this();
561 * GameTick::doPlayerCollisions - spread fire between players
562 * GameTick::ProcessDevKeys - press f to ignite
563 * Person::DoStuff - spread fire from lit campfires and bushes
565 void Person::CatchFire()
567 XYZ flatfacing, flatvelocity;
569 for (int i = 0; i < 10; i++) {
570 howmany = fabs(Random() % (skeleton.joints.size()));
572 flatvelocity = skeleton.joints[howmany].velocity;
573 flatfacing = skeleton.joints[howmany].position * scale + coords;
575 flatvelocity = velocity;
576 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
578 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
583 emit_sound_at(firestartsound, coords);
585 emit_stream_at(stream_firesound, coords);
593 * idle animation for this creature (depending on status)
595 int Person::getIdle()
597 if (Dialog::inDialog() && (howactive == typeactive) && PersonType::types[creature].hasAnimTalkIdle()) {
598 return PersonType::types[creature].animTalkIdle;
600 if (hasvictim && (victim != this->shared_from_this())) {
601 if ((!victim->dead && victim->aitype != passivetype &&
602 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
603 victim->id < Person::players.size())) {
604 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
605 return PersonType::types[creature].animFightIdle;
607 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
608 if (weapons[weaponids[weaponactive]].getType() == knife) {
609 return knifefightidleanim;
611 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
612 return swordfightidlebothanim;
614 if (weapons[weaponids[weaponactive]].getType() == sword) {
615 return swordfightidleanim;
617 if (weapons[weaponids[weaponactive]].getType() == staff) {
618 return swordfightidleanim;
621 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
622 return fightsidestep;
626 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
629 if (howactive == typesitting) {
632 if (howactive == typesittingwall) {
635 if (howactive == typesleeping) {
638 if (howactive == typedead1) {
641 if (howactive == typedead2) {
644 if (howactive == typedead3) {
647 if (howactive == typedead4) {
650 return PersonType::types[creature].animBounceIdle;
654 * crouch animation for this creature
656 int Person::getCrouch()
658 return PersonType::types[creature].animCrouch;
662 * running animation for this creature (can be upright or all fours)
666 if (superruntoggle && (weaponactive == -1)) {
667 return PersonType::types[creature].animRunning;
669 return PersonType::types[creature].animRun;
675 int Person::getStop()
677 return PersonType::types[creature].animStop;
682 int Person::getLanding()
684 return PersonType::types[creature].animLanding;
689 int Person::getLandhard()
691 return PersonType::types[creature].animLandingHard;
697 * Person::DoAnimations
700 SolidHitBonus(int playerid)
702 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
703 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
705 award_bonus(playerid, solidhit);
710 * spawns blood effects
712 void Person::DoBlood(float howmuch, int which)
714 // FIXME: should abstract out inputs
715 static int bleedxint, bleedyint;
717 if (bloodtoggle && !Tutorial::active) {
718 if (bleeding <= 0 && spurt) {
720 for (int i = 0; i < 3; i++) {
721 // emit blood particles
724 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
725 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
726 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
727 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
730 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
731 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
732 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
733 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
736 if (Random() % 2 == 0) { // 50% chance
737 for (int i = 0; i < 3; i++) {
738 if (Random() % 2 != 0) {
739 // emit teeth particles
742 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
743 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
746 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
747 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
751 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
753 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
755 Sprite::setLastSpriteSpecial(3); // sets it to teeth
761 // FIXME: manipulating attributes
762 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
765 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) {
766 bleedxint = abs(Random() % 512);
767 bleedyint = abs(Random() % 512);
771 bleedy /= realtexdetail;
772 bleedx /= realtexdetail;
773 direction = abs(Random() % 2) * 2 - 1;
782 * spawns big blood effects and ???
783 * modifies character's skin texture
785 void Person::DoBloodBig(float howmuch, int which)
787 static int bleedxint, bleedyint, i, j;
789 if (howmuch && id == 0) {
793 if (!Tutorial::active || id == 0) {
794 if (aitype != playercontrolled && howmuch > 0) {
798 if (creature == wolftype) {
799 int i = abs(Random() % 2);
801 whichsound = snarlsound;
804 whichsound = snarl2sound;
807 if (creature == rabbittype) {
808 int i = abs(Random() % 2);
810 whichsound = rabbitpainsound;
812 if (i == 1 && howmuch >= 2) {
813 whichsound = rabbitpain1sound;
817 if (whichsound != -1) {
818 emit_sound_at(whichsound, coords);
824 if (id == 0 && howmuch > 0) {
828 if (bloodtoggle && decalstoggle && !Tutorial::active) {
829 if (bleeding <= 0 && spurt) {
831 for (int i = 0; i < 3; i++) {
832 // emit blood particles
833 // FIXME: copypaste from above
836 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
837 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
838 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
839 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
842 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
843 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
844 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
845 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
850 // weird texture manipulation code follows.
851 // looks like this is painting blood onto the character's skin texture
852 // FIXME: surely there's a better way
854 int offsetx = 0, offsety = 0;
856 offsety = Random() % 40;
857 offsetx = abs(Random() % 60);
859 if (which == 190 || which == 185) {
860 offsety = Random() % 40;
861 offsetx = abs(Random() % 100) - 20;
864 offsety = Random() % 10;
865 offsetx = Random() % 10;
868 offsety = Random() % 20;
869 offsetx = Random() % 20;
871 if (which == 220 || which == 215) {
880 for (i = 0; i < 512; i++) {
881 for (j = 0; j < 512; j++) {
882 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) {
910 if (endx > 512 - 1) {
913 if (endy > 512 - 1) {
923 startx /= realtexdetail;
924 starty /= realtexdetail;
925 endx /= realtexdetail;
926 endy /= realtexdetail;
928 int texdetailint = realtexdetail;
930 for (i = startx; i < endx; i++) {
931 for (j = starty; j < endy; j++) {
932 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) {
933 color = Random() % 85 + 170;
934 where = i * skeleton.skinsize * 3 + j * 3;
935 if (skeleton.skinText[where + 0] > color / 2) {
936 skeleton.skinText[where + 0] = color / 2;
938 skeleton.skinText[where + 1] = 0;
939 skeleton.skinText[where + 2] = 0;
943 skeleton.drawmodel.textureptr.bind();
948 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) {
949 bleedxint = abs(Random() % 512);
950 bleedyint = abs(Random() % 512);
952 bleedy = bleedxint + offsetx;
953 bleedx = bleedyint + offsety;
954 bleedy /= realtexdetail;
955 bleedx /= realtexdetail;
962 if (bleedx > skeleton.skinsize - 1) {
963 bleedx = skeleton.skinsize - 1;
965 if (bleedy > skeleton.skinsize - 1) {
966 bleedy = skeleton.skinsize - 1;
968 direction = abs(Random() % 2) * 2 - 1;
970 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
971 deathbleeding += bleeding;
972 bloodloss += bleeding * 3;
974 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
975 if (abs(Random() % 2) == 0) {
976 aitype = gethelptype;
979 aitype = attacktypecutoff;
989 * similar to DoBloodBig
991 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
995 static XYZ startpoint, endpoint, colpoint, movepoint;
996 static float rotationpoint;
998 static XYZ p1, p2, p3, p0;
1001 float coordsx, coordsy;
1004 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1006 if (!skeleton.free) {
1007 where = DoRotation(where, 0, -yaw, 0);
1011 startpoint.y += 100;
1016 // ray testing for a tri in the character model
1017 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1018 if (whichtri != -1) {
1019 // low level geometry math
1021 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1022 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1023 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1025 bary.x = distsq(&p0, &p1);
1026 bary.y = distsq(&p0, &p2);
1027 bary.z = distsq(&p0, &p3);
1029 total = bary.x + bary.y + bary.z;
1034 bary.x = 1 - bary.x;
1035 bary.y = 1 - bary.y;
1036 bary.z = 1 - bary.z;
1038 total = bary.x + bary.y + bary.z;
1043 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1044 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1045 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1046 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1047 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1048 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1049 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;
1050 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;
1052 if (bleeding <= 0 && spurt) {
1054 for (int i = 0; i < 3; i++) {
1055 // emit blood particles
1056 // FIXME: more copypaste code
1058 if (skeleton.free) {
1059 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1060 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1061 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1062 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1065 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1066 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1067 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1068 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1073 // texture manipulation follows
1075 int offsetx = 0, offsety = 0;
1076 offsetx = (1 + coordsy) * 512 - 291;
1077 offsety = coordsx * 512 - 437;
1084 for (i = 0; i < 512; i++) {
1085 for (j = 0; j < 512; j++) {
1086 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) {
1113 if (endx > 512 - 1) {
1116 if (endy > 512 - 1) {
1119 if (endx < startx) {
1122 if (endy < starty) {
1126 startx /= realtexdetail;
1127 starty /= realtexdetail;
1128 endx /= realtexdetail;
1129 endy /= realtexdetail;
1131 int texdetailint = realtexdetail;
1133 for (i = startx; i < endx; i++) {
1134 for (j = starty; j < endy; j++) {
1135 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) {
1136 color = Random() % 85 + 170;
1137 where = i * skeleton.skinsize * 3 + j * 3;
1138 if (skeleton.skinText[where + 0] > color / 2) {
1139 skeleton.skinText[where + 0] = color / 2;
1141 skeleton.skinText[where + 1] = 0;
1142 skeleton.skinText[where + 2] = 0;
1143 } 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) {
1144 color = Random() % 85 + 170;
1145 where = i * skeleton.skinsize * 3 + j * 3;
1146 if (skeleton.skinText[where + 0] > color / 2) {
1147 skeleton.skinText[where + 0] = color / 2;
1149 skeleton.skinText[where + 1] = 0;
1150 skeleton.skinText[where + 2] = 0;
1154 skeleton.drawmodel.textureptr.bind();
1157 bleedy = (1 + coordsy) * 512;
1158 bleedx = coordsx * 512;
1159 bleedy /= realtexdetail;
1160 bleedx /= realtexdetail;
1167 if (bleedx > skeleton.skinsize - 1) {
1168 bleedx = skeleton.skinsize - 1;
1170 if (bleedy > skeleton.skinsize - 1) {
1171 bleedy = skeleton.skinsize - 1;
1173 direction = abs(Random() % 2) * 2 - 1;
1175 if (whichtri == -1) {
1179 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1180 deathbleeding += bleeding;
1181 bloodloss += bleeding * 3;
1183 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1184 if (abs(Random() % 2) == 0) {
1185 aitype = gethelptype;
1188 aitype = attacktypecutoff;
1199 * guessing this performs a reversal
1201 void Person::Reverse()
1203 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1207 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1211 if (animTarget == sweepanim) {
1212 animTarget = sweepreversedanim;
1213 animCurrent = sweepreversedanim;
1214 victim->animCurrent = sweepreversalanim;
1215 victim->animTarget = sweepreversalanim;
1217 if (animTarget == spinkickanim) {
1218 animTarget = spinkickreversedanim;
1219 animCurrent = spinkickreversedanim;
1220 victim->animCurrent = spinkickreversalanim;
1221 victim->animTarget = spinkickreversalanim;
1223 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1224 if (animTarget == rabbittacklinganim) {
1227 victim->frameCurrent = 6;
1228 victim->frameTarget = 7;
1230 animTarget = upunchreversedanim;
1231 animCurrent = upunchreversedanim;
1232 victim->animCurrent = upunchreversalanim;
1233 victim->animTarget = upunchreversalanim;
1235 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1236 if (victim->weaponactive != -1) {
1237 victim->throwtogglekeydown = 1;
1238 XYZ tempVelocity = victim->velocity * .2;
1239 if (tempVelocity.x == 0) {
1240 tempVelocity.x = .1;
1242 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1243 victim->num_weapons--;
1244 if (victim->num_weapons) {
1245 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1246 if (victim->weaponstuck == victim->num_weapons) {
1247 victim->weaponstuck = 0;
1251 victim->weaponactive = -1;
1252 for (unsigned j = 0; j < Person::players.size(); j++) {
1253 Person::players[j]->wentforweapon = 0;
1257 animTarget = staffhitreversedanim;
1258 animCurrent = staffhitreversedanim;
1259 victim->animCurrent = staffhitreversalanim;
1260 victim->animTarget = staffhitreversalanim;
1262 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1263 if (victim->weaponactive != -1) {
1264 victim->throwtogglekeydown = 1;
1265 XYZ tempVelocity = victim->velocity * .2;
1266 if (tempVelocity.x == 0) {
1267 tempVelocity.x = .1;
1269 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1270 victim->num_weapons--;
1271 if (victim->num_weapons) {
1272 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1273 if (victim->weaponstuck == victim->num_weapons) {
1274 victim->weaponstuck = 0;
1278 victim->weaponactive = -1;
1279 for (unsigned j = 0; j < Person::players.size(); j++) {
1280 Person::players[j]->wentforweapon = 0;
1283 animTarget = staffspinhitreversedanim;
1284 animCurrent = staffspinhitreversedanim;
1285 victim->animCurrent = staffspinhitreversalanim;
1286 victim->animTarget = staffspinhitreversalanim;
1288 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1289 if (victim->weaponactive != -1) {
1290 victim->throwtogglekeydown = 1;
1291 XYZ tempVelocity = victim->velocity * .2;
1292 if (tempVelocity.x == 0) {
1293 tempVelocity.x = .1;
1295 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1296 victim->num_weapons--;
1297 if (victim->num_weapons) {
1298 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1299 if (victim->weaponstuck == victim->num_weapons) {
1300 victim->weaponstuck = 0;
1304 victim->weaponactive = -1;
1305 for (unsigned j = 0; j < Person::players.size(); j++) {
1306 Person::players[j]->wentforweapon = 0;
1309 animTarget = swordslashreversedanim;
1310 animCurrent = swordslashreversedanim;
1311 victim->animCurrent = swordslashreversalanim;
1312 victim->animTarget = swordslashreversalanim;
1314 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1315 if (victim->weaponactive != -1) {
1316 victim->throwtogglekeydown = 1;
1317 XYZ tempVelocity = victim->velocity * .2;
1318 if (tempVelocity.x == 0) {
1319 tempVelocity.x = .1;
1321 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1322 victim->num_weapons--;
1323 if (victim->num_weapons) {
1324 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1325 if (victim->weaponstuck == victim->num_weapons) {
1326 victim->weaponstuck = 0;
1330 victim->weaponactive = -1;
1331 for (unsigned j = 0; j < Person::players.size(); j++) {
1332 Person::players[j]->wentforweapon = 0;
1335 animTarget = knifeslashreversedanim;
1336 animCurrent = knifeslashreversedanim;
1337 victim->animCurrent = knifeslashreversalanim;
1338 victim->animTarget = knifeslashreversalanim;
1340 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1341 victim->targettilt2 = targettilt2;
1342 victim->frameCurrent = frameCurrent;
1343 victim->frameTarget = frameTarget;
1344 victim->target = target;
1345 victim->velocity = 0;
1346 victim->oldcoords = victim->coords;
1347 victim->coords = coords;
1348 victim->targetyaw = targetyaw;
1349 victim->yaw = targetyaw;
1350 victim->victim = this->shared_from_this();
1352 if (animTarget == winduppunchanim) {
1353 animTarget = winduppunchblockedanim;
1354 victim->animTarget = blockhighleftanim;
1355 victim->frameTarget = 1;
1356 victim->target = .5;
1357 victim->victim = this->shared_from_this();
1358 victim->targetyaw = targetyaw + 180;
1360 if (animTarget == wolfslapanim) {
1361 animTarget = winduppunchblockedanim;
1362 victim->animTarget = blockhighleftanim;
1363 victim->frameTarget = 1;
1364 victim->target = .5;
1365 victim->victim = this->shared_from_this();
1366 victim->targetyaw = targetyaw + 180;
1368 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1369 animTarget = swordslashparriedanim;
1370 parriedrecently = .4;
1371 victim->parriedrecently = 0;
1372 victim->animTarget = swordslashparryanim;
1373 victim->frameTarget = 1;
1374 victim->target = .5;
1375 victim->victim = this->shared_from_this();
1376 victim->targetyaw = targetyaw + 180;
1378 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1379 if (victim->weaponactive != -1) {
1380 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1381 if (weapons[victim->weaponids[0]].getType() == staff) {
1382 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1384 if (weapons[weaponids[0]].getType() == staff) {
1385 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1387 emit_sound_at(swordstaffsound, victim->coords);
1389 emit_sound_at(metalhitsound, victim->coords);
1393 victim->Puff(righthand);
1395 victim->frameTarget = 0;
1396 victim->animTarget = staggerbackhighanim;
1397 victim->targetyaw = targetyaw + 180;
1399 aim = DoRotation(facing, 0, 90, 0) * 21;
1401 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1402 victim->num_weapons--;
1403 if (victim->num_weapons) {
1404 victim->weaponids[0] = victim->weaponids[num_weapons];
1405 if (victim->weaponstuck == victim->num_weapons) {
1406 victim->weaponstuck = 0;
1409 victim->weaponactive = -1;
1410 for (unsigned i = 0; i < Person::players.size(); i++) {
1411 Person::players[i]->wentforweapon = 0;
1415 if (abs(Random() % 20) == 0) {
1416 if (weaponactive != -1) {
1417 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1418 if (weapons[victim->weaponids[0]].getType() == staff) {
1419 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1421 if (weapons[weaponids[0]].getType() == staff) {
1422 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1425 emit_sound_at(swordstaffsound, coords);
1427 emit_sound_at(metalhitsound, coords);
1435 animTarget = staggerbackhighanim;
1436 targetyaw = targetyaw + 180;
1438 aim = DoRotation(facing, 0, 90, 0) * 21;
1440 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1443 weaponids[0] = weaponids[num_weapons];
1444 if (weaponstuck == num_weapons) {
1449 for (unsigned i = 0; i < Person::players.size(); i++) {
1450 Person::players[i]->wentforweapon = 0;
1455 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1456 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1457 victim->animTarget = dodgebackanim;
1458 victim->frameTarget = 0;
1462 rotatetarget = coords - victim->coords;
1463 Normalise(&rotatetarget);
1464 victim->targetyaw = -asin(0 - rotatetarget.x);
1465 victim->targetyaw *= 360 / 6.28;
1466 if (rotatetarget.z < 0) {
1467 victim->targetyaw = 180 - victim->targetyaw;
1470 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1472 victim->lastattack3 = victim->lastattack2;
1473 victim->lastattack2 = victim->lastattack;
1474 victim->lastattack = victim->animTarget;
1476 victim->animTarget = sweepanim;
1477 victim->frameTarget = 0;
1481 rotatetarget = coords - victim->coords;
1482 Normalise(&rotatetarget);
1483 victim->targetyaw = -asin(0 - rotatetarget.x);
1484 victim->targetyaw *= 360 / 6.28;
1485 if (rotatetarget.z < 0) {
1486 victim->targetyaw = 180 - victim->targetyaw;
1489 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1491 victim->lastattack3 = victim->lastattack2;
1492 victim->lastattack2 = victim->lastattack;
1493 victim->lastattack = victim->animTarget;
1499 victim->velocity = 0;
1501 if (aitype != playercontrolled) {
1503 if (escapednum < 2) {
1504 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1505 if ((Random() % chances) == 0) {
1511 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1519 void Person::DoDamage(float howmuch)
1523 damagetaken += howmuch / power;
1525 damagedealt += howmuch / power;
1529 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1534 if (!Tutorial::active) {
1535 damage += howmuch / power;
1536 permanentdamage += howmuch / 2 / power;
1537 superpermanentdamage += howmuch / 4 / power;
1540 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1543 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1548 camerashake += howmuch / 100;
1549 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1550 blackout = damage / damagetolerance;
1558 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1559 aitype = attacktypecutoff;
1561 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1562 if (abs(Random() % 2) == 0) {
1563 aitype = gethelptype;
1566 aitype = attacktypecutoff;
1571 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1574 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1575 if (skeleton.free) {
1576 flatvelocity2 = skeleton.joints[i].velocity;
1577 flatfacing2 = skeleton.joints[i].position * scale + coords;
1579 flatvelocity2 = velocity;
1580 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1582 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1583 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1584 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1585 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1586 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1587 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1590 emit_sound_at(splattersound, coords);
1595 if (!dead && creature == wolftype) {
1596 award_bonus(0, Wolfbonus);
1603 if (!Tutorial::active || id == 0) {
1604 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1605 int whichsound = -1;
1607 if (creature == wolftype) {
1608 int i = abs(Random() % 2);
1610 whichsound = snarlsound;
1613 whichsound = snarl2sound;
1616 if (creature == rabbittype) {
1617 int i = abs(Random() % 2);
1619 whichsound = rabbitpainsound;
1621 if (i == 1 && damage > damagetolerance) {
1622 whichsound = rabbitpain1sound;
1626 if (whichsound != -1) {
1627 emit_sound_at(whichsound, coords);
1628 addEnvSound(coords);
1636 * calculate/animate head facing direction?
1638 void Person::DoHead()
1640 static XYZ rotatearound;
1642 static float lookspeed = 500;
1644 if (!freeze && !winfreeze) {
1647 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1648 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1650 while (targetheadyaw > 180) {
1651 targetheadyaw -= 360;
1653 while (targetheadyaw < -180) {
1654 targetheadyaw += 360;
1657 if (targetheadyaw > 160) {
1658 targetheadpitch = targetheadpitch * -1;
1660 if (targetheadyaw < -160) {
1661 targetheadpitch = targetheadpitch * -1;
1663 if (targetheadyaw > 160) {
1664 targetheadyaw = targetheadyaw - 180;
1666 if (targetheadyaw < -160) {
1667 targetheadyaw = targetheadyaw + 180;
1670 if (targetheadpitch > 120) {
1671 targetheadpitch = 120;
1673 if (targetheadpitch < -120) {
1674 targetheadpitch = -120;
1676 if (targetheadyaw > 120) {
1677 targetheadyaw = 120;
1679 if (targetheadyaw < -120) {
1680 targetheadyaw = -120;
1684 targetheadpitch = 0;
1687 if (targetheadyaw > 80) {
1690 if (targetheadyaw < -80) {
1691 targetheadyaw = -80;
1693 if (targetheadpitch > 50) {
1694 targetheadpitch = 50;
1696 if (targetheadpitch < -50) {
1697 targetheadpitch = -50;
1701 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1702 headyaw = targetheadyaw;
1703 } else if (headyaw > targetheadyaw) {
1704 headyaw -= multiplier * lookspeed;
1705 } else if (headyaw < targetheadyaw) {
1706 headyaw += multiplier * lookspeed;
1709 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1710 headpitch = targetheadpitch;
1711 } else if (headpitch > targetheadpitch) {
1712 headpitch -= multiplier * lookspeed / 2;
1713 } else if (headpitch < targetheadpitch) {
1714 headpitch += multiplier * lookspeed / 2;
1717 rotatearound = jointPos(neck);
1718 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1722 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1723 facing = DoRotation(facing, headpitch * .4, 0, 0);
1724 facing = DoRotation(facing, 0, headyaw * .4, 0);
1727 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1728 facing = DoRotation(facing, headpitch * .8, 0, 0);
1729 facing = DoRotation(facing, 0, headyaw * .8, 0);
1732 if (animTarget == walkanim) {
1733 facing = DoRotation(facing, headpitch * .6, 0, 0);
1734 facing = DoRotation(facing, 0, headyaw * .6, 0);
1737 skeleton.specialforward[0] = facing;
1738 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1739 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1740 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1741 skeleton.FindRotationMuscle(i, animTarget);
1748 * ragdolls character?
1750 void Person::RagDoll(bool checkcollision)
1755 if (!skeleton.free) {
1759 if (id == 0 && isFlip()) {
1767 facing = DoRotation(facing, 0, yaw, 0);
1769 skeleton.freetime = 0;
1771 skeleton.longdead = 0;
1774 skeleton.broken = 0;
1775 skeleton.spinny = 1;
1777 skeleton.freefall = 1;
1779 if (!isnormal(velocity.x)) {
1782 if (!isnormal(velocity.y)) {
1785 if (!isnormal(velocity.z)) {
1788 if (!isnormal(yaw)) {
1791 if (!isnormal(coords.x)) {
1794 if (!isnormal(tilt)) {
1797 if (!isnormal(tilt2)) {
1801 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1802 skeleton.joints[i].delay = 0;
1803 skeleton.joints[i].locked = 0;
1804 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1805 if (!isnormal(skeleton.joints[i].position.x)) {
1806 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1808 if (!isnormal(skeleton.joints[i].position.x)) {
1809 skeleton.joints[i].position = coords;
1811 skeleton.joints[i].position.y += .1;
1812 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1813 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1816 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1817 skeleton.joints[i].velocity = 0;
1818 skeleton.joints[i].velchange = 0;
1820 skeleton.DoConstraints(&coords, &scale);
1821 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1822 skeleton.DoConstraints(&coords, &scale);
1823 skeleton.DoConstraints(&coords, &scale);
1824 skeleton.DoConstraints(&coords, &scale);
1825 skeleton.DoConstraints(&coords, &scale);
1828 speed = targetFrame().speed * 2;
1829 if (currentFrame().speed > targetFrame().speed) {
1830 speed = currentFrame().speed * 2;
1833 speed = transspeed * 2;
1838 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1839 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
1840 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);
1842 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1844 change.x = (float)(Random() % 100) / 100;
1845 change.y = (float)(Random() % 100) / 100;
1846 change.z = (float)(Random() % 100) / 100;
1847 skeleton.joints[i].velocity += change;
1848 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1850 change.x = (float)(Random() % 100) / 100;
1851 change.y = (float)(Random() % 100) / 100;
1852 change.z = (float)(Random() % 100) / 100;
1853 skeleton.joints[i].velchange += change;
1854 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1857 if (checkcollision) {
1860 if (!skeleton.joints.empty()) {
1863 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1864 average += skeleton.joints[j].position;
1866 average /= skeleton.joints.size();
1867 coords += average * scale;
1868 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1869 skeleton.joints[j].position -= average;
1873 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1874 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1875 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1876 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1879 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1880 coords.x = lowpoint.x;
1881 coords.z = lowpoint.z;
1890 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1891 velocity += skeleton.joints[i].velocity * scale;
1893 velocity /= skeleton.joints.size();
1896 if (Random() % 2 == 0) {
1897 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1898 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1899 weapons[weaponids[0]].velocity.x += .01;
1902 weaponids[0] = weaponids[num_weapons];
1903 if (weaponstuck == num_weapons) {
1908 for (unsigned i = 0; i < Person::players.size(); i++) {
1909 Person::players[i]->wentforweapon = 0;
1914 animTarget = bounceidleanim;
1915 animCurrent = bounceidleanim;
1923 void Person::FootLand(bodypart whichfoot, float opacity)
1925 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1926 cerr << "FootLand called on wrong bodypart" << endl;
1929 static XYZ terrainlight;
1930 static XYZ footvel, footpoint;
1931 if (opacity >= 1 || skiddelay <= 0) {
1934 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1935 if (distsq(&footpoint, &viewer)) {
1936 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1938 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1939 footvel = velocity / 5;
1940 if (footvel.y < .8) {
1943 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1944 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1945 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1946 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1947 if (environment == snowyenvironment) {
1948 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1950 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1952 } else if (environment == grassyenvironment) {
1953 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1954 } else if (environment == desertenvironment) {
1955 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1957 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1961 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1962 footvel = velocity / 5;
1963 if (footvel.y < .8) {
1966 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1967 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1968 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1975 * make a puff effect at a body part (dust effect?)
1977 void Person::Puff(int whichlabel)
1979 static XYZ footvel, footpoint;
1982 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1983 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1987 * I think I added this in an attempt to clean up code
1989 void Person::setTargetAnimation(int animation)
1991 animTarget = animation;
2000 void Person::DoAnimations()
2002 if (!skeleton.free) {
2003 static float oldtarget;
2005 if (isIdle() && animCurrent != getIdle()) {
2006 normalsupdatedelay = 0;
2009 if (animTarget == tempanim || animCurrent == tempanim) {
2010 Animation::animations[tempanim] = tempanimation;
2012 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2019 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2020 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2022 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2025 if (!crouchkeydown && velocity.y >= -15) {
2029 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2034 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2036 if (normaldotproduct(targfacing, velocity) >= -.3) {
2037 animTarget = flipanim;
2039 animTarget = backflipanim;
2041 crouchtogglekeydown = 1;
2050 if (Animation::animations[animTarget].attack != reversed) {
2053 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2054 crouchtogglekeydown = 0;
2055 if (aitype == playercontrolled) {
2059 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2063 crouchtogglekeydown = 1;
2067 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2069 normalsupdatedelay = 0;
2074 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2076 emit_sound_at(fireendsound, coords);
2077 pause_sound(stream_firesound);
2081 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2082 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2085 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2086 if (normaldotproduct(victim->facing, facing) > 0) {
2087 victim->animTarget = rabbittackledbackanim;
2089 victim->animTarget = rabbittackledfrontanim;
2091 victim->frameTarget = 2;
2094 victim->targetyaw = yaw;
2095 if (victim->aitype == gethelptype) {
2096 victim->DoDamage(victim->damagetolerance - victim->damage);
2098 //victim->DoDamage(30);
2099 if (creature == wolftype) {
2101 emit_sound_at(clawslicesound, victim->coords);
2103 victim->DoBloodBig(1 / victim->armorhead, 210);
2105 award_bonus(id, TackleBonus,
2106 victim->aitype == gethelptype ? 50 : 0);
2110 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2111 if (weapons[weaponids[0]].getType() == knife) {
2112 if (weaponactive == -1) {
2114 } else if (weaponactive == 0) {
2118 if (weaponactive == -1) {
2119 emit_sound_at(knifesheathesound, coords);
2121 if (weaponactive != -1) {
2122 emit_sound_at(knifedrawsound, coords, 128);
2125 drawtogglekeydown = 1;
2128 if (!Tutorial::active || id == 0) {
2129 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2130 int whichsound = -1;
2132 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2133 if (targetFrame().label == 1) {
2134 whichsound = footstepsound;
2136 whichsound = footstepsound2;
2138 if (targetFrame().label == 1) {
2139 FootLand(leftfoot, 1);
2141 if (targetFrame().label == 2) {
2142 FootLand(rightfoot, 1);
2144 if (targetFrame().label == 3 && isRun()) {
2145 FootLand(rightfoot, 1);
2146 FootLand(leftfoot, 1);
2149 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2150 if (targetFrame().label == 1) {
2151 whichsound = footstepsound3;
2153 whichsound = footstepsound4;
2158 if (targetFrame().label == 1) {
2159 whichsound = footstepsound3;
2161 whichsound = footstepsound4;
2164 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2165 if (Animation::animations[animTarget].attack != neutral) {
2166 unsigned r = abs(Random() % 3);
2168 whichsound = lowwhooshsound;
2171 whichsound = midwhooshsound;
2174 whichsound = highwhooshsound;
2177 if (Animation::animations[animTarget].attack == neutral) {
2178 whichsound = movewhooshsound;
2180 } else if (targetFrame().label == 4) {
2181 whichsound = knifeswishsound;
2183 if (targetFrame().label == 8 && !Tutorial::active) {
2184 whichsound = landsound2;
2187 if (whichsound != -1) {
2188 emit_sound_at(whichsound, coords, 256.);
2191 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2192 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2193 addEnvSound(coords, 15);
2195 addEnvSound(coords, 6);
2200 if (targetFrame().label == 3) {
2202 emit_sound_at(whichsound, coords, 128.);
2209 if (!Tutorial::active || id == 0) {
2210 if (speechdelay <= 0) {
2211 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2212 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2213 int whichsound = -1;
2214 if (targetFrame().label == 4 && aitype != playercontrolled) {
2215 if (Animation::animations[animTarget].attack != neutral) {
2216 unsigned r = abs(Random() % 4);
2217 whichsound = PersonType::types[creature].soundsAttack[r];
2222 if (whichsound != -1) {
2223 emit_sound_at(whichsound, coords);
2230 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2231 FootLand(leftfoot, 1);
2232 FootLand(rightfoot, 1);
2236 currentoffset = targetoffset;
2237 frameTarget = frameCurrent;
2238 animCurrent = animTarget;
2241 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2242 for (unsigned i = 0; i < weapons.size(); i++) {
2243 if (weapons[i].owner == -1) {
2244 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2245 if (distsq(&coords, &weapons[i].position) >= 1) {
2246 if (weapons[i].getType() != staff) {
2247 emit_sound_at(knifedrawsound, coords, 128.);
2257 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2258 for (unsigned i = 0; i < weapons.size(); i++) {
2259 bool willwork = true;
2260 if (weapons[i].owner != -1) {
2261 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2262 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2263 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2269 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2270 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2271 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2272 bool fleshstuck = false;
2273 if (weapons[i].owner != -1) {
2274 if (victim->weaponstuck != -1) {
2275 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2281 emit_sound_at(fleshstabremovesound, coords, 128.);
2283 if (weapons[i].getType() != staff) {
2284 emit_sound_at(knifedrawsound, coords, 128.);
2287 if (weapons[i].owner != -1) {
2288 victim = Person::players[weapons[i].owner];
2289 if (victim->num_weapons == 1) {
2290 victim->num_weapons = 0;
2292 victim->num_weapons = 1;
2295 //victim->weaponactive=-1;
2296 victim->skeleton.longdead = 0;
2297 victim->skeleton.free = 1;
2298 victim->skeleton.broken = 0;
2300 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2301 victim->skeleton.joints[j].velchange = 0;
2302 victim->skeleton.joints[j].locked = 0;
2308 Normalise(&relative);
2309 XYZ footvel, footpoint;
2311 footpoint = weapons[i].position;
2312 if (victim->weaponstuck != -1) {
2313 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2315 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2317 weapons[i].bloody = 2;
2318 weapons[i].blooddrip = 5;
2319 victim->weaponstuck = -1;
2322 if (victim->num_weapons > 0) {
2323 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2324 victim->weaponstuck = 0;
2326 if (victim->weaponids[0] == int(i)) {
2327 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2331 victim->jointVel(abdomen) += relative * 6;
2332 victim->jointVel(neck) += relative * 6;
2333 victim->jointVel(rightshoulder) += relative * 6;
2334 victim->jointVel(leftshoulder) += relative * 6;
2343 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2344 if (weaponactive == -1) {
2346 } else if (weaponactive == 0) {
2348 if (num_weapons == 2) {
2350 buffer = weaponids[0];
2351 weaponids[0] = weaponids[1];
2352 weaponids[1] = buffer;
2355 if (weaponactive == -1) {
2356 emit_sound_at(knifesheathesound, coords, 128.);
2358 if (weaponactive != -1) {
2359 emit_sound_at(knifedrawsound, coords, 128.);
2363 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2364 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2365 Normalise(&rotatetarget);
2366 targetyaw = -asin(0 - rotatetarget.x);
2367 targetyaw *= 360 / 6.28;
2368 if (rotatetarget.z < 0) {
2369 targetyaw = 180 - targetyaw;
2372 if (animTarget == walljumprightkickanim) {
2375 if (animTarget == walljumpleftkickanim) {
2382 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2386 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2394 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2395 animTarget = rabbittackleanim;
2397 emit_sound_at(jumpsound, coords);
2405 targetloc = velocity;
2406 Normalise(&targetloc);
2407 targetloc += coords;
2408 for (unsigned i = 0; i < Person::players.size(); i++) {
2410 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2411 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2416 if (closestid != -1) {
2417 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2419 victim = Person::players[closestid];
2420 coords = victim->coords;
2421 animCurrent = rabbittacklinganim;
2422 animTarget = rabbittacklinganim;
2426 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2427 rotatetarget = coords - victim->coords;
2428 Normalise(&rotatetarget);
2429 targetyaw = -asin(0 - rotatetarget.x);
2430 targetyaw *= 360 / 6.28;
2431 if (rotatetarget.z < 0) {
2432 targetyaw = 180 - targetyaw;
2435 if (animTarget != rabbitrunninganim) {
2436 emit_sound_at(jumpsound, coords, 128.);
2443 float damagemult = 1 * power;
2444 if (creature == wolftype) {
2445 damagemult = 2.5 * power;
2448 damagemult /= victim->damagetolerance / 200;
2450 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)) {
2451 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2452 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2457 if (Random() % 2 || creature == wolftype) {
2460 if (creature == wolftype) {
2464 if (!Tutorial::active) {
2465 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2467 if (creature == wolftype) {
2468 emit_sound_at(clawslicesound, victim->coords, 128.);
2470 victim->DoBloodBig(2 / victim->armorhead, 175);
2474 relative = victim->coords - coords;
2476 Normalise(&relative);
2477 relative = DoRotation(relative, 0, -90, 0);
2478 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2479 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2481 victim->jointVel(head) += relative * damagemult * 200;
2483 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2489 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2490 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2495 if (Random() % 2 || creature == wolftype) {
2497 if (creature == wolftype) {
2501 emit_sound_at(whooshhitsound, victim->coords);
2502 if (creature == wolftype) {
2503 emit_sound_at(clawslicesound, victim->coords, 128.);
2505 victim->DoBloodBig(2, 175);
2509 relative = victim->coords - coords;
2511 Normalise(&relative);
2513 Normalise(&relative);
2514 relative = DoRotation(relative, 0, 90, 0);
2515 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2516 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2518 victim->jointVel(head) += relative * damagemult * 100;
2520 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2524 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2525 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2532 if (!Tutorial::active) {
2533 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2535 if (creature == wolftype) {
2536 emit_sound_at(clawslicesound, victim->coords, 128.);
2538 victim->DoBloodBig(2 / victim->armorhead, 175);
2544 Normalise(&relative);
2545 relative = DoRotation(relative, 0, -90, 0);
2546 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2547 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2549 victim->jointVel(head) += relative * damagemult * 200;
2551 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2553 if (victim->damage > victim->damagetolerance) {
2554 award_bonus(id, style);
2561 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2562 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2569 if (!Tutorial::active) {
2570 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2572 if (creature == wolftype) {
2573 emit_sound_at(clawslicesound, victim->coords, 128.);
2575 victim->DoBloodBig(2 / victim->armorhead, 175);
2581 Normalise(&relative);
2582 relative = DoRotation(relative, 0, 90, 0);
2583 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2584 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2586 victim->jointVel(head) += relative * damagemult * 200;
2588 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2590 if (victim->damage > victim->damagetolerance) {
2591 award_bonus(id, style);
2598 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2599 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2608 emit_sound_at(whooshhitsound, victim->coords);
2611 relative = victim->coords - coords;
2613 Normalise(&relative);
2614 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2615 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2617 victim->jointVel(head) += relative * damagemult * 100;
2619 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2623 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2624 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2629 emit_sound_at(whooshhitsound, victim->coords, 128.);
2631 victim->skeleton.longdead = 0;
2632 victim->skeleton.free = 1;
2633 victim->skeleton.broken = 0;
2634 victim->skeleton.spinny = 1;
2636 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2637 victim->skeleton.joints[i].velchange = 0;
2638 victim->skeleton.joints[i].delay = 0;
2639 victim->skeleton.joints[i].locked = 0;
2640 //victim->skeleton.joints[i].velocity=0;
2646 Normalise(&relative);
2647 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2648 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2649 victim->skeleton.joints[i].position.y += relative.y * .3;
2650 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2651 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2653 victim->Puff(abdomen);
2654 victim->jointVel(abdomen).y = relative.y * 400;
2658 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2659 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2664 if (!Tutorial::active) {
2665 emit_sound_at(heavyimpactsound, coords, 128.);
2668 relative = victim->coords - coords;
2670 Normalise(&relative);
2671 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2672 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2674 victim->Puff(abdomen);
2675 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2679 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2680 victim->jointVel(abdomen) += relative * damagemult * 300;
2684 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2685 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2690 if (!Tutorial::active) {
2691 emit_sound_at(thudsound, coords);
2694 victim->skeleton.longdead = 0;
2695 victim->skeleton.free = 1;
2696 victim->skeleton.broken = 0;
2697 victim->skeleton.spinny = 1;
2699 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2700 victim->skeleton.joints[i].velchange = 0;
2701 //victim->skeleton.joints[i].delay=0;
2702 victim->skeleton.joints[i].locked = 0;
2705 relative = victim->coords - coords;
2706 Normalise(&relative);
2708 Normalise(&relative);
2709 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2710 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2712 if (!victim->dead) {
2716 victim->Puff(abdomen);
2717 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2718 victim->jointVel(abdomen) += relative * damagemult * 200;
2720 if (!victim->dead) {
2726 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2729 if (!victim->skeleton.free) {
2735 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2736 emit_sound_at(knifesheathesound, coords, 128.);
2739 if (victim && hasvictim) {
2740 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2742 XYZ where, startpoint, endpoint, movepoint, colpoint;
2743 float rotationpoint;
2745 if (weapons[weaponids[weaponactive]].getType() == knife) {
2746 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2747 where -= victim->coords;
2748 if (!victim->skeleton.free) {
2749 where = DoRotation(where, 0, -victim->yaw, 0);
2753 startpoint.y += 100;
2757 if (weapons[weaponids[weaponactive]].getType() == sword) {
2758 where = weapons[weaponids[weaponactive]].position;
2759 where -= victim->coords;
2760 if (!victim->skeleton.free) {
2761 where = DoRotation(where, 0, -victim->yaw, 0);
2764 where = weapons[weaponids[weaponactive]].tippoint;
2765 where -= victim->coords;
2766 if (!victim->skeleton.free) {
2767 where = DoRotation(where, 0, -victim->yaw, 0);
2771 if (weapons[weaponids[weaponactive]].getType() == staff) {
2772 where = weapons[weaponids[weaponactive]].position;
2773 where -= victim->coords;
2774 if (!victim->skeleton.free) {
2775 where = DoRotation(where, 0, -victim->yaw, 0);
2778 where = weapons[weaponids[weaponactive]].tippoint;
2779 where -= victim->coords;
2780 if (!victim->skeleton.free) {
2781 where = DoRotation(where, 0, -victim->yaw, 0);
2787 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2789 if (whichtri != -1) {
2790 if (victim->dead != 2) {
2791 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2792 if (!victim->dead) {
2793 award_bonus(id, FinishedBonus);
2797 weapons[weaponids[weaponactive]].bloody = 2;
2800 victim->skeleton.longdead = 0;
2801 victim->skeleton.free = 1;
2802 victim->skeleton.broken = 0;
2804 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2805 victim->skeleton.joints[i].velchange = 0;
2806 victim->skeleton.joints[i].locked = 0;
2807 //victim->skeleton.joints[i].velocity=0;
2809 emit_sound_at(fleshstabsound, coords, 128);
2811 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2812 weapons[weaponids[weaponactive]].blooddrip += 5;
2813 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2815 if (whichtri == -1) {
2817 emit_sound_at(knifesheathesound, coords, 128.);
2823 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2825 emit_sound_at(knifedrawsound, coords, 128);
2828 if (victim && hasvictim) {
2829 XYZ footvel, footpoint;
2831 emit_sound_at(fleshstabremovesound, coords, 128.);
2834 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2836 if (weapons[weaponids[weaponactive]].getType() == sword) {
2837 XYZ where, startpoint, endpoint, movepoint;
2838 float rotationpoint;
2841 where = weapons[weaponids[weaponactive]].position;
2842 where -= victim->coords;
2843 if (!victim->skeleton.free) {
2844 where = DoRotation(where, 0, -victim->yaw, 0);
2847 where = weapons[weaponids[weaponactive]].tippoint;
2848 where -= victim->coords;
2849 if (!victim->skeleton.free) {
2850 where = DoRotation(where, 0, -victim->yaw, 0);
2856 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2857 footpoint += victim->coords;
2859 if (whichtri == -1) {
2860 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2863 if (weapons[weaponids[weaponactive]].getType() == staff) {
2864 XYZ where, startpoint, endpoint, movepoint;
2865 float rotationpoint;
2868 where = weapons[weaponids[weaponactive]].position;
2869 where -= victim->coords;
2870 if (!victim->skeleton.free) {
2871 where = DoRotation(where, 0, -victim->yaw, 0);
2874 where = weapons[weaponids[weaponactive]].tippoint;
2875 where -= victim->coords;
2876 if (!victim->skeleton.free) {
2877 where = DoRotation(where, 0, -victim->yaw, 0);
2883 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2884 footpoint += victim->coords;
2886 if (whichtri == -1) {
2887 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2890 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2892 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2893 victim->skeleton.longdead = 0;
2894 victim->skeleton.free = 1;
2895 victim->skeleton.broken = 0;
2897 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2898 victim->skeleton.joints[i].velchange = 0;
2899 victim->skeleton.joints[i].locked = 0;
2900 //victim->skeleton.joints[i].velocity=0;
2906 Normalise(&relative);
2907 //victim->Puff(abdomen);
2909 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2912 if (victim->bloodloss < victim->damagetolerance) {
2913 victim->bloodloss += 1000;
2917 victim->jointVel(abdomen) += relative * damagemult * 20;
2921 if (!hasvictim && onterrain) {
2922 weapons[weaponids[weaponactive]].bloody = 0;
2923 weapons[weaponids[weaponactive]].blooddrip = 0;
2927 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2928 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2937 if (!Tutorial::active) {
2938 emit_sound_at(heavyimpactsound, victim->coords, 128);
2943 relative = victim->coords - coords;
2945 Normalise(&relative);
2946 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2947 victim->skeleton.joints[i].velocity = relative * 30;
2949 victim->jointVel(head) += relative * damagemult * 150;
2951 victim->frameTarget = 0;
2952 victim->animTarget = staggerbackhardanim;
2953 victim->targetyaw = targetyaw + 180;
2955 victim->stunned = 1;
2958 victim->Puff(abdomen);
2959 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2965 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2966 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2971 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2972 if (!Tutorial::active) {
2973 emit_sound_at(thudsound, victim->coords);
2975 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2976 if (!Tutorial::active) {
2977 emit_sound_at(whooshhitsound, victim->coords);
2980 if (!Tutorial::active) {
2981 emit_sound_at(heavyimpactsound, victim->coords);
2985 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
2989 relative = victim->coords - coords;
2991 Normalise(&relative);
2993 Normalise(&relative);
2994 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2995 victim->skeleton.joints[i].velocity = relative * 5;
2997 victim->jointVel(abdomen) += relative * damagemult * 400;
2999 victim->frameTarget = 0;
3000 victim->animTarget = staggerbackhardanim;
3001 victim->targetyaw = targetyaw + 180;
3003 victim->stunned = 1;
3005 victim->Puff(abdomen);
3006 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3012 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3013 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3014 if (victim->id == 0) {
3017 emit_sound_at(landsound2, victim->coords);
3023 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3024 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3025 if (victim->id == 0) {
3029 if (weaponactive != -1) {
3030 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3031 if (weapons[victim->weaponids[0]].getType() == staff) {
3032 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3034 if (weapons[weaponids[0]].getType() == staff) {
3035 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3038 emit_sound_at(swordstaffsound, victim->coords);
3040 emit_sound_at(metalhitsound, victim->coords);
3048 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3049 if (weaponactive != -1) {
3052 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);
3054 weapons[weaponids[0]].thrown(aim * 50);
3057 weaponids[0] = weaponids[num_weapons];
3063 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3065 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3067 if (!Tutorial::active) {
3068 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3071 award_bonus(id, Slicebonus);
3072 if (!Tutorial::active) {
3073 emit_sound_at(knifeslicesound, victim->coords);
3075 //victim->jointVel(abdomen)+=relative*damagemult*200;
3076 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3077 if (victim->id != 0 || difficulty == 2) {
3078 victim->frameTarget = 0;
3079 victim->animTarget = staggerbackhardanim;
3080 victim->targetyaw = targetyaw + 180;
3084 victim->lowreversaldelay = 0;
3085 victim->highreversaldelay = 0;
3086 if (aitype != playercontrolled) {
3087 weaponmissdelay = .6;
3090 if (!Tutorial::active) {
3091 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3092 weapons[weaponids[weaponactive]].bloody = 1;
3094 weapons[weaponids[weaponactive]].blooddrip += 3;
3097 XYZ footvel, footpoint;
3099 if (skeleton.free) {
3100 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3102 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3104 if (Tutorial::active) {
3105 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3108 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3110 footvel = DoRotation(facing, 0, 90, 0) * .8;
3111 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3112 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3113 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3114 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3116 victim->DoDamage(damagemult * 0);
3120 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3121 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3122 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3123 award_bonus(id, Slashbonus);
3125 if (!Tutorial::active) {
3126 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3127 victim->DoBloodBig(2 / victim->armorhigh, 190);
3129 victim->DoBloodBig(2 / victim->armorhigh, 185);
3131 victim->deathbleeding = 1;
3132 emit_sound_at(swordslicesound, victim->coords);
3133 victim->frameTarget = 0;
3134 victim->animTarget = staggerbackhardanim;
3135 victim->targetyaw = targetyaw + 180;
3137 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3138 weapons[weaponids[weaponactive]].bloody = 1;
3140 weapons[weaponids[weaponactive]].blooddrip += 3;
3142 float bloodlossamount;
3143 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3144 victim->bloodloss += bloodlossamount / victim->armorhigh;
3145 victim->DoDamage(damagemult * 0);
3147 XYZ footvel, footpoint;
3149 if (skeleton.free) {
3150 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3152 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3155 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3157 footvel = DoRotation(facing, 0, 90, 0) * .8;
3159 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3160 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3161 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3162 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3165 if (victim->weaponactive != -1) {
3166 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3167 if (weapons[victim->weaponids[0]].getType() == staff) {
3168 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3170 if (weapons[weaponids[0]].getType() == staff) {
3171 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3174 emit_sound_at(swordstaffsound, victim->coords);
3176 emit_sound_at(metalhitsound, victim->coords);
3181 victim->Puff(righthand);
3183 victim->frameTarget = 0;
3184 victim->animTarget = staggerbackhighanim;
3185 victim->targetyaw = targetyaw + 180;
3187 aim = DoRotation(facing, 0, 90, 0) * 21;
3189 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3190 victim->num_weapons--;
3191 if (victim->num_weapons) {
3192 victim->weaponids[0] = victim->weaponids[num_weapons];
3193 if (victim->weaponstuck == victim->num_weapons) {
3194 victim->weaponstuck = 0;
3197 victim->weaponactive = -1;
3198 for (unsigned i = 0; i < Person::players.size(); i++) {
3199 Person::players[i]->wentforweapon = 0;
3205 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3206 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3207 if (!Tutorial::active) {
3208 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3213 if (Random() % 2 || creature == wolftype) {
3216 emit_sound_at(staffheadsound, victim->coords);
3220 relative = victim->coords - coords;
3222 Normalise(&relative);
3223 relative = DoRotation(relative, 0, 90, 0);
3225 Normalise(&relative);
3226 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3227 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3229 victim->jointVel(head) += relative * damagemult * 230;
3230 victim->jointVel(neck) += relative * damagemult * 230;
3232 if (!Tutorial::active) {
3233 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3235 award_bonus(id, solidhit, 30);
3240 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3241 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3242 if (!Tutorial::active) {
3243 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3248 if (Random() % 2 || creature == wolftype) {
3251 emit_sound_at(staffheadsound, victim->coords);
3255 relative = victim->coords - coords;
3257 Normalise(&relative);
3258 relative = DoRotation(relative, 0, -90, 0);
3259 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3260 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3262 victim->jointVel(head) += relative * damagemult * 220;
3263 victim->jointVel(neck) += relative * damagemult * 220;
3265 if (!Tutorial::active) {
3266 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3268 award_bonus(id, solidhit, 60);
3273 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3274 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3276 if (!Tutorial::active) {
3277 if (!victim->dead) {
3278 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3283 if (Random() % 2 || creature == wolftype) {
3286 emit_sound_at(staffbodysound, victim->coords);
3288 victim->skeleton.longdead = 0;
3289 victim->skeleton.free = 1;
3290 victim->skeleton.broken = 0;
3292 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3293 victim->skeleton.joints[i].velchange = 0;
3294 victim->skeleton.joints[i].locked = 0;
3295 //victim->skeleton.joints[i].velocity=0;
3302 Normalise(&relative);
3303 if (!victim->dead) {
3304 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3305 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3307 victim->jointVel(abdomen) += relative * damagemult * 40;
3310 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3311 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3314 victim->Puff(abdomen);
3315 if (!Tutorial::active) {
3316 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3318 if (!victim->dead) {
3319 award_bonus(id, solidhit, 40);
3325 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3326 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3332 relative = victim->coords - coords;
3334 Normalise(&relative);
3338 if (Animation::animations[victim->animTarget].height == lowheight) {
3344 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3345 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3347 victim->jointVel(head) += relative * damagemult * 200;
3348 if (!Tutorial::active) {
3349 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3352 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3353 if (victim->howactive == typesleeping) {
3354 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3356 if (creature == wolftype) {
3357 emit_sound_at(clawslicesound, victim->coords, 128.);
3359 victim->DoBloodBig(2 / victim->armorhead, 175);
3362 if (victim->damage >= victim->damagetolerance) {
3365 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3366 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3368 victim->jointVel(abdomen) += relative * damagemult * 200;
3369 victim->frameTarget = 0;
3370 victim->animTarget = staggerbackhighanim;
3371 victim->targetyaw = targetyaw + 180;
3373 if (!Tutorial::active) {
3374 emit_sound_at(landsound2, victim->coords, 128.);
3376 victim->Puff(abdomen);
3377 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3378 if (creature == wolftype) {
3379 emit_sound_at(clawslicesound, victim->coords, 128.);
3381 victim->DoBloodBig(2 / victim->armorhigh, 170);
3387 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3388 if ((victim->animTarget != jumpupanim) &&
3389 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3390 (victim != this->shared_from_this())) {
3395 if (!Tutorial::active) {
3396 emit_sound_at(landsound2, victim->coords, 128.);
3399 relative = victim->coords - coords;
3401 Normalise(&relative);
3403 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3406 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3407 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3409 relative = DoRotation(relative, 0, -90, 0);
3411 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3412 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) {
3413 victim->skeleton.joints[i].velocity = relative * 80;
3416 victim->Puff(rightankle);
3417 victim->Puff(leftankle);
3418 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3420 if (victim->damage >= victim->damagetolerance) {
3423 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3424 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3426 relative = DoRotation(relative, 0, -90, 0);
3427 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3428 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) {
3429 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3432 victim->jointVel(abdomen) += relative * damagemult * 200;
3433 victim->frameTarget = 0;
3434 victim->animTarget = staggerbackhighanim;
3435 victim->targetyaw = targetyaw + 180;
3437 if (!Tutorial::active) {
3438 emit_sound_at(landsound2, victim->coords, 128.);
3440 victim->Puff(abdomen);
3441 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3448 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3449 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3458 if (!Tutorial::active) {
3459 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3461 if (creature == wolftype) {
3462 emit_sound_at(clawslicesound, victim->coords, 128);
3464 victim->DoBloodBig(2 / victim->armorhigh, 170);
3468 relative = victim->coords - oldcoords;
3470 Normalise(&relative);
3471 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3472 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3474 victim->jointVel(abdomen) += relative * damagemult * 200;
3475 victim->Puff(abdomen);
3476 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3478 award_bonus(id, Reversal);
3481 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3482 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3483 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3484 takeWeapon(victim->weaponids[victim->weaponactive]);
3485 victim->num_weapons--;
3486 if (victim->num_weapons > 0) {
3487 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3489 victim->weaponactive = -1;
3494 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3503 emit_sound_at(whooshhitsound, victim->coords, 128.);
3506 relative = victim->coords - oldcoords;
3508 Normalise(&relative);
3509 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3510 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3512 victim->jointVel(abdomen) += relative * damagemult * 200;
3514 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3517 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3527 award_bonus(id, staffreversebonus);
3529 if (!Tutorial::active) {
3530 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3533 award_bonus(id, staffreversebonus); // Huh, again?
3536 relative = victim->coords - oldcoords;
3538 Normalise(&relative);
3539 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3540 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3542 victim->jointVel(abdomen) += relative * damagemult * 200;
3544 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3547 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3553 Normalise(&relative);
3555 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3556 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3558 victim->jointVel(lefthand) *= .1;
3559 victim->jointVel(leftwrist) *= .2;
3560 victim->jointVel(leftelbow) *= .5;
3561 victim->jointVel(leftshoulder) *= .7;
3562 victim->jointVel(righthand) *= .1;
3563 victim->jointVel(rightwrist) *= .2;
3564 victim->jointVel(rightelbow) *= .5;
3565 victim->jointVel(rightshoulder) *= .7;
3567 victim->Puff(abdomen);
3568 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3570 award_bonus(id, Reversal);
3574 if (weaponactive != -1 || creature == wolftype) {
3577 if (creature == rabbittype && weaponactive != -1) {
3578 if (weapons[weaponids[0]].getType() == staff) {
3583 if (weaponactive != -1) {
3584 victim->DoBloodBig(2 / victim->armorhigh, 225);
3585 emit_sound_at(knifeslicesound, victim->coords);
3586 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3587 weapons[weaponids[weaponactive]].bloody = 1;
3589 weapons[weaponids[weaponactive]].blooddrip += 3;
3591 if (weaponactive == -1 && creature == wolftype) {
3592 emit_sound_at(clawslicesound, victim->coords, 128.);
3594 victim->DoBloodBig(2 / victim->armorhigh, 175);
3599 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3605 Normalise(&relative);
3607 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3608 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3610 victim->jointVel(lefthand) *= .1 - 1;
3611 victim->jointVel(leftwrist) *= .2 - 1;
3612 victim->jointVel(leftelbow) *= .5 - 1;
3613 victim->jointVel(leftshoulder) *= .7 - 1;
3614 victim->jointVel(righthand) *= .1 - 1;
3615 victim->jointVel(rightwrist) *= .2 - 1;
3616 victim->jointVel(rightelbow) *= .5 - 1;
3617 victim->jointVel(rightshoulder) *= .7 - 1;
3619 award_bonus(id, swordreversebonus);
3622 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3631 if (!Tutorial::active) {
3632 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3636 relative = victim->coords - oldcoords;
3638 Normalise(&relative);
3639 relative = DoRotation(relative, 0, -90, 0);
3640 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3641 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3643 victim->jointVel(abdomen) += relative * damagemult * 200;
3644 victim->Puff(abdomen);
3645 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3647 award_bonus(id, Reversal);
3650 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3653 victim->skeleton.spinny = 0;
3655 relative = facing * -1;
3657 Normalise(&relative);
3658 if (victim->id == 0) {
3661 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3662 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3664 victim->damage = victim->damagetolerance;
3665 victim->permanentdamage = victim->damagetolerance - 1;
3668 if (weaponactive != -1 || creature == wolftype) {
3671 if (creature == rabbittype && weaponactive != -1) {
3672 if (weapons[weaponids[0]].getType() == staff) {
3677 if (weaponactive != -1) {
3678 victim->DoBloodBig(200, 225);
3679 emit_sound_at(knifeslicesound, victim->coords);
3681 weapons[weaponids[weaponactive]].bloody = 2;
3683 weapons[weaponids[weaponactive]].blooddrip += 5;
3686 if (creature == wolftype && weaponactive == -1) {
3687 emit_sound_at(clawslicesound, victim->coords, 128.);
3689 victim->DoBloodBig(2, 175);
3692 award_bonus(id, spinecrusher);
3695 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3696 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3698 if (animTarget == knifefollowanim) {
3699 victim->DoBloodBig(200, 210);
3701 if (animTarget == knifesneakattackanim) {
3702 XYZ footvel, footpoint;
3704 footpoint = weapons[weaponids[0]].tippoint;
3706 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3708 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3709 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3710 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3711 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3712 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3713 victim->DoBloodBig(200, 195);
3714 award_bonus(id, tracheotomy);
3716 if (animTarget == knifefollowanim) {
3717 award_bonus(id, Stabbonus);
3718 XYZ footvel, footpoint;
3720 footpoint = weapons[weaponids[0]].tippoint;
3722 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3724 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3725 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3726 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3727 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3728 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3730 victim->bloodloss += 10000;
3731 victim->velocity = 0;
3732 emit_sound_at(fleshstabsound, victim->coords);
3734 weapons[weaponids[weaponactive]].bloody = 2;
3736 weapons[weaponids[weaponactive]].blooddrip += 5;
3740 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3742 victim->velocity = 0;
3743 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3744 victim->skeleton.joints[i].velocity = 0;
3746 if (animTarget == knifefollowanim) {
3748 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3749 victim->skeleton.joints[i].velocity = 0;
3752 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3753 emit_sound_at(fleshstabremovesound, victim->coords);
3755 weapons[weaponids[weaponactive]].bloody = 2;
3757 weapons[weaponids[weaponactive]].blooddrip += 5;
3759 XYZ footvel, footpoint;
3761 footpoint = weapons[weaponids[0]].tippoint;
3763 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3765 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
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, footvel * 5, 1, 1, 1, .3, 1);
3769 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3773 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3774 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3775 award_bonus(id, backstab);
3779 XYZ footvel, footpoint;
3781 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3783 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3785 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3786 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3787 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3788 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3789 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3790 victim->DoBloodBig(200, 180);
3791 victim->DoBloodBig(200, 215);
3792 victim->bloodloss += 10000;
3793 victim->velocity = 0;
3794 emit_sound_at(fleshstabsound, victim->coords);
3796 weapons[weaponids[weaponactive]].bloody = 2;
3798 weapons[weaponids[weaponactive]].blooddrip += 5;
3802 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3804 victim->velocity = 0;
3805 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3806 victim->skeleton.joints[i].velocity = 0;
3808 if (weaponactive != -1) {
3809 emit_sound_at(fleshstabremovesound, victim->coords);
3811 weapons[weaponids[weaponactive]].bloody = 2;
3813 weapons[weaponids[weaponactive]].blooddrip += 5;
3815 XYZ footvel, footpoint;
3817 footpoint = weapons[weaponids[0]].tippoint;
3819 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3821 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3822 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3823 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3824 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3825 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3829 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3838 if (weaponactive == -1) {
3839 if (!Tutorial::active) {
3840 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3845 if (weaponactive != -1 || creature == wolftype) {
3848 if (creature == rabbittype && weaponactive != -1) {
3849 if (weapons[weaponids[0]].getType() == staff) {
3854 if (weaponactive != -1) {
3855 victim->DoBloodBig(2 / victim->armorhead, 225);
3856 emit_sound_at(knifeslicesound, victim->coords);
3857 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3858 weapons[weaponids[weaponactive]].bloody = 1;
3860 weapons[weaponids[weaponactive]].blooddrip += 3;
3862 if (weaponactive == -1 && creature == wolftype) {
3863 emit_sound_at(clawslicesound, victim->coords, 128.);
3865 victim->DoBloodBig(2 / victim->armorhead, 175);
3869 award_bonus(id, Reversal);
3874 relative = facing * -1;
3876 Normalise(&relative);
3877 relative = DoRotation(relative, 0, 90, 0);
3879 Normalise(&relative);
3880 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3881 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3883 victim->jointVel(head) += relative * damagemult * 200;
3884 if (victim->damage < victim->damagetolerance - 100) {
3885 victim->velocity = relative * 200;
3887 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3888 victim->velocity = 0;
3891 if (animTarget == sweepreversalanim && ((Animation::animations[animTarget].frames[frameCurrent].label == 9 && victim->damage < victim->damagetolerance) || (Animation::animations[animTarget].frames[frameCurrent].label == 7 && victim->damage > victim->damagetolerance))) {
3895 relative = facing * -1;
3897 Normalise(&relative);
3898 relative = DoRotation(relative, 0, 90, 0);
3900 Normalise(&relative);
3901 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3902 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3904 victim->jointVel(head) += relative * damagemult * 200;
3907 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
3908 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3909 award_bonus(id, reverseko);
3915 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3918 animTarget = getIdle();
3919 FootLand(leftfoot, 1);
3920 FootLand(rightfoot, 1);
3922 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3923 animTarget = rollanim;
3925 emit_sound_at(movewhooshsound, coords, 128.);
3927 if (animCurrent == staggerbackhighanim) {
3928 animTarget = getIdle();
3930 if (animCurrent == staggerbackhardanim) {
3931 animTarget = getIdle();
3933 if (animCurrent == removeknifeanim) {
3934 animTarget = getIdle();
3936 if (animCurrent == crouchremoveknifeanim) {
3937 animTarget = getCrouch();
3939 if (animCurrent == backhandspringanim) {
3940 animTarget = getIdle();
3942 if (animCurrent == dodgebackanim) {
3943 animTarget = getIdle();
3945 if (animCurrent == drawleftanim) {
3946 animTarget = getIdle();
3948 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3949 animTarget = getIdle();
3950 if (animCurrent == crouchdrawrightanim) {
3951 animTarget = getCrouch();
3953 if (weaponactive == -1) {
3955 } else if (weaponactive == 0) {
3957 if (num_weapons == 2) {
3959 buffer = weaponids[0];
3960 weaponids[0] = weaponids[1];
3961 weaponids[1] = buffer;
3965 if (weaponactive == -1) {
3966 emit_sound_at(knifesheathesound, coords, 128.);
3968 if (weaponactive != -1) {
3969 emit_sound_at(knifedrawsound, coords, 128.);
3972 if (animCurrent == rollanim) {
3973 animTarget = getCrouch();
3974 FootLand(leftfoot, 1);
3975 FootLand(rightfoot, 1);
3978 if (animTarget == walljumprightkickanim) {
3981 if (animTarget == walljumpleftkickanim) {
3984 animTarget = jumpdownanim;
3986 if (animCurrent == climbanim) {
3987 animTarget = getCrouch();
3989 coords += facing * .1;
3990 if (!isnormal(coords.x)) {
4001 if (animTarget == rabbitkickreversalanim) {
4002 animTarget = getCrouch();
4005 if (animTarget == jumpreversalanim) {
4006 animTarget = getCrouch();
4009 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4010 if (attackkeydown && animTarget != walljumpfrontanim) {
4012 float closestdist = -1;
4014 if (Person::players.size() > 1) {
4015 for (unsigned i = 0; i < Person::players.size(); i++) {
4016 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4017 distance = distsq(&Person::players[i]->coords, &coords);
4018 if (closestdist == -1 || distance < closestdist) {
4019 closestdist = distance;
4025 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4026 victim = Person::players[closest];
4027 animTarget = walljumprightkickanim;
4029 XYZ rotatetarget = victim->coords - coords;
4030 Normalise(&rotatetarget);
4031 yaw = -asin(0 - rotatetarget.x);
4033 if (rotatetarget.z < 0) {
4036 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4037 velocity = (victim->coords - coords) * 4;
4042 if (animTarget == walljumpbackanim) {
4043 animTarget = backflipanim;
4045 velocity = facing * -8;
4048 resume_stream(whooshsound);
4051 if (animTarget == walljumprightanim) {
4052 animTarget = rightflipanim;
4056 velocity = DoRotation(facing, 0, 30, 0) * -8;
4059 if (animTarget == walljumpfrontanim) {
4060 animTarget = frontflipanim;
4064 velocity = facing * 8;
4068 resume_stream(whooshsound);
4071 if (animTarget == walljumpleftanim) {
4072 if (attackkeydown) {
4074 float closestdist = -1;
4076 if (Person::players.size() > 1) {
4077 for (unsigned i = 0; i < Person::players.size(); i++) {
4078 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4079 distance = distsq(&Person::players[i]->coords, &coords);
4080 if (closestdist == -1 || distance < closestdist) {
4081 closestdist = distance;
4087 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4088 victim = Person::players[closest];
4089 animTarget = walljumpleftkickanim;
4091 XYZ rotatetarget = victim->coords - coords;
4092 Normalise(&rotatetarget);
4093 yaw = -asin(0 - rotatetarget.x);
4095 if (rotatetarget.z < 0) {
4098 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4099 velocity = (victim->coords - coords) * 4;
4104 if (animTarget != walljumpleftkickanim) {
4105 animTarget = leftflipanim;
4109 velocity = DoRotation(facing, 0, -30, 0) * -8;
4113 resume_stream(whooshsound);
4116 if (animTarget == sneakattackanim) {
4117 animCurrent = getCrouch();
4118 animTarget = getCrouch();
4125 transspeed = 1000000;
4126 targetheadyaw += 180;
4127 coords -= facing * .7;
4129 coords.y = terrain.getHeight(coords.x, coords.z);
4134 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4135 animTarget = getIdle();
4138 coords.y = terrain.getHeight(coords.x, coords.z);
4143 if (animCurrent == knifefollowanim) {
4144 animTarget = getIdle();
4147 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4148 float ycoords = oldcoords.y;
4149 animTarget = getStop();
4154 transspeed = 1000000;
4155 targetheadyaw += 180;
4156 if (!isnormal(coords.x)) {
4159 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4160 oldcoords = coords + facing * .5;
4161 } else if (animCurrent == sweepreversalanim) {
4162 oldcoords = coords + facing * 1.1;
4163 } else if (animCurrent == upunchreversalanim) {
4164 oldcoords = coords + facing * 1.5;
4167 targetheadyaw += 180;
4170 } else if (animCurrent == knifeslashreversalanim) {
4171 oldcoords = coords + facing * .5;
4174 targetheadyaw += 90;
4177 } else if (animCurrent == staffspinhitreversalanim) {
4180 targetheadyaw += 180;
4185 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4187 oldcoords.y = ycoords;
4189 currentoffset = coords - oldcoords;
4195 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4200 if (Animation::animations[animTarget].attack == reversed) {
4202 if (animTarget == sweepreversedanim) {
4205 animTarget = backhandspringanim;
4207 emit_sound_at(landsound, coords, 128);
4209 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4210 animTarget = rollanim;
4213 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4214 coords.y = oldcoords.y;
4216 if (animCurrent == knifeslashreversedanim) {
4217 animTarget = rollanim;
4222 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4223 coords.y = oldcoords.y;
4227 animTarget = jumpdownanim;
4230 animTarget = getIdle();
4232 if (wasLandhard()) {
4233 animTarget = getIdle();
4235 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4236 animTarget = getIdle();
4238 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4239 coords.y = oldcoords.y;
4240 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4241 targetoffset.y = coords.y;
4243 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4245 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4246 currentoffset.y -= (coords.y - targetoffset.y);
4247 coords.y = targetoffset.y;
4249 normalsupdatedelay = 0;
4251 if (animCurrent == upunchanim) {
4252 animTarget = getStop();
4253 normalsupdatedelay = 0;
4256 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4260 if (num_weapons > 0) {
4261 if (weapons[0].getType() == staff) {
4270 rabbitkickragdoll = 1;
4272 if (animCurrent == rabbitkickreversedanim) {
4278 skeleton.spinny = 0;
4279 SolidHitBonus(!id); // FIXME: tricky id
4283 animTarget = rollanim;
4286 pause_sound(whooshsound);
4291 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4295 skeleton.spinny = 0;
4297 if (animCurrent == jumpreversedanim) {
4303 skeleton.spinny = 0;
4304 SolidHitBonus(!id); // FIXME: tricky id
4308 animTarget = rollanim;
4309 coords += facing * 2;
4311 pause_sound(whooshsound);
4317 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) {
4318 animTarget = getupfromfrontanim;
4320 } else if (Animation::animations[animCurrent].attack == normalattack) {
4321 animTarget = getIdle();
4324 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4325 animTarget = blockhighleftstrikeanim;
4327 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4328 animTarget = getIdle();
4331 if (animCurrent == spinkickanim && victim->skeleton.free) {
4332 if (creature == rabbittype) {
4333 animTarget = fightidleanim;
4339 if (isIdle() && !wasIdle()) {
4340 normalsupdatedelay = 0;
4343 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4344 animTarget = jumpdownanim;
4347 if (!skeleton.free) {
4349 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4350 if (!isRun() || !wasRun()) {
4351 if (targetFrame().speed > currentFrame().speed) {
4352 target += multiplier * targetFrame().speed * speed * 2;
4354 if (targetFrame().speed <= currentFrame().speed) {
4355 target += multiplier * currentFrame().speed * speed * 2;
4358 if (isRun() && wasRun()) {
4360 tempspeed = velspeed;
4361 if (tempspeed < 10 * speedmult) {
4362 tempspeed = 10 * speedmult;
4364 /* FIXME - mixed of target and current here, is that intended? */
4365 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4367 } else if (transspeed) {
4368 target += multiplier * transspeed * speed * 2;
4370 if (!isRun() || !wasRun()) {
4371 if (targetFrame().speed > currentFrame().speed) {
4372 target += multiplier * targetFrame().speed * 2;
4374 if (targetFrame().speed <= currentFrame().speed) {
4375 target += multiplier * currentFrame().speed * 2;
4380 if (animCurrent != animTarget) {
4381 target = (target + oldtarget) / 2;
4385 frameCurrent = frameTarget;
4389 rot = targetrot * target;
4390 yaw += rot - oldrot;
4396 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4397 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4399 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4401 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4402 skeleton.joints[i].position = currentFrame().joints[i].position;
4405 skeleton.FindForwards();
4407 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4408 if (skeleton.muscles[i].visible) {
4409 skeleton.FindRotationMuscle(i, animTarget);
4412 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4413 if (skeleton.muscles[i].visible) {
4414 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4415 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4417 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4418 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4420 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4421 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4427 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4428 skeleton.joints[i].position = targetFrame().joints[i].position;
4431 skeleton.FindForwards();
4433 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4434 if (skeleton.muscles[i].visible) {
4435 skeleton.FindRotationMuscle(i, animTarget);
4438 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4439 if (skeleton.muscles[i].visible) {
4440 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4441 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4443 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4444 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4446 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4447 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4449 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4450 skeleton.muscles[i].newrotate3 -= 360;
4452 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4453 skeleton.muscles[i].newrotate3 += 360;
4455 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4456 skeleton.muscles[i].newrotate2 -= 360;
4458 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4459 skeleton.muscles[i].newrotate2 += 360;
4461 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4462 skeleton.muscles[i].newrotate1 -= 360;
4464 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4465 skeleton.muscles[i].newrotate1 += 360;
4471 oldanimCurrent = animCurrent;
4472 oldanimTarget = animTarget;
4473 oldframeTarget = frameTarget;
4474 oldframeCurrent = frameCurrent;
4476 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4477 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4478 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4480 offset = currentoffset * (1 - target) + targetoffset * target;
4481 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4482 if (skeleton.muscles[i].visible) {
4483 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4484 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4485 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4490 if (isLanding() && landhard) {
4494 animTarget = getLandhard();
4507 void Person::DoStuff()
4509 static XYZ terrainnormal;
4510 static XYZ flatfacing;
4511 static XYZ flatvelocity;
4512 static float flatvelspeed;
4513 static int bloodsize;
4514 static int startx, starty, endx, endy;
4515 static GLubyte color;
4516 static XYZ bloodvel;
4518 onfiredelay -= multiplier;
4519 if (onfiredelay < 0 && onfire) {
4520 if (Random() % 2 == 0) {
4526 crouchkeydowntime += multiplier;
4527 if (!crouchkeydown) {
4528 crouchkeydowntime = 0;
4530 jumpkeydowntime += multiplier;
4531 if (!jumpkeydown && skeleton.free) {
4532 jumpkeydowntime = 0;
4535 if (hostile || damage > 0 || bloodloss > 0) {
4539 if (isIdle() || isRun()) {
4543 if (num_weapons == 1 && weaponactive != -1) {
4548 blooddimamount -= multiplier * .3;
4550 speechdelay -= multiplier;
4551 texupdatedelay -= multiplier;
4552 interestdelay -= multiplier;
4553 flamedelay -= multiplier;
4554 parriedrecently -= multiplier;
4556 victim = this->shared_from_this();
4561 speed = 1.1 * speedmult;
4563 speed = 1.0 * speedmult;
4565 if (!skeleton.free) {
4566 rabbitkickragdoll = 0;
4571 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4574 if (id != 0 && creature == wolftype && difficulty == 2) {
4576 if (aitype != passivetype) {
4578 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) {
4585 if (animTarget == wolfrunninganim && !superruntoggle) {
4586 animTarget = getRun();
4590 if (weaponactive == -1 && num_weapons > 0) {
4591 if (weapons[weaponids[0]].getType() == staff) {
4597 burnt += multiplier;
4602 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4604 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4611 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4612 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4616 while (flamedelay < 0 && onfire) {
4618 int howmany = fabs(Random() % (skeleton.joints.size()));
4619 if (skeleton.free) {
4620 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4621 flatfacing = skeleton.joints[howmany].position * scale + coords;
4623 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4624 flatvelocity = (coords - oldcoords) / multiplier / 2;
4626 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4629 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4631 int howmany = fabs(Random() % (skeleton.joints.size()));
4632 if (skeleton.free) {
4633 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4634 flatfacing = skeleton.joints[howmany].position * scale + coords;
4636 flatvelocity = (coords - oldcoords) / multiplier / 2;
4637 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4639 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4643 bleeding -= multiplier * .3;
4644 if (bloodtoggle == 2) {
4645 skeleton.drawmodel.textureptr.bind();
4646 if ((bleeding <= 0) && (detail != 2)) {
4652 if (neckspurtamount > 0) {
4653 neckspurtamount -= multiplier;
4654 neckspurtdelay -= multiplier * 3;
4655 neckspurtparticledelay -= multiplier * 3;
4656 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4659 if (skeleton.free) {
4660 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4661 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4662 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4664 bloodvel.z = 5 * neckspurtamount;
4665 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4666 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4667 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4669 neckspurtparticledelay = .05;
4671 if (neckspurtdelay < 0) {
4676 if (deathbleeding > 0 && dead != 2) {
4677 if (deathbleeding < 5) {
4678 bleeddelay -= deathbleeding * multiplier / 4;
4680 bleeddelay -= 5 * multiplier / 4;
4682 if (bleeddelay < 0 && bloodtoggle) {
4687 if (skeleton.free) {
4688 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4689 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4691 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4692 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4696 bloodloss += deathbleeding * multiplier * 80;
4697 deathbleeding -= multiplier * 1.6;
4698 if (deathbleeding < 0) {
4701 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4702 if (weaponactive != -1) {
4703 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4704 weapons[weaponids[0]].velocity.x += .01;
4707 weaponids[0] = weaponids[num_weapons];
4708 if (weaponstuck == num_weapons) {
4713 for (unsigned i = 0; i < Person::players.size(); i++) {
4714 Person::players[i]->wentforweapon = 0;
4722 if (!dead && creature == wolftype) {
4723 award_bonus(0, Wolfbonus);
4726 if (animTarget == knifefollowedanim && !skeleton.free) {
4727 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4728 skeleton.joints[i].velocity = 0;
4729 skeleton.joints[i].velocity.y = -2;
4732 if (id != 0 && unconscioustime > .1) {
4740 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4741 texupdatedelay = .12;
4743 bloodsize = 5 - realtexdetail;
4747 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4748 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4749 endx = startx + bloodsize;
4750 endy = starty + bloodsize;
4760 if (endx > skeleton.skinsize - 1) {
4761 endx = skeleton.skinsize - 1;
4764 if (endy > skeleton.skinsize - 1) {
4765 endy = skeleton.skinsize - 1;
4768 if (endx < startx) {
4771 if (endy < starty) {
4775 for (int i = startx; i < endx; i++) {
4776 for (int j = starty; j < endy; j++) {
4777 if (Random() % 2 == 0) {
4778 color = Random() % 85 + 170;
4779 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4780 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4782 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4783 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4788 skeleton.drawmodel.textureptr.bind();
4792 if (skeleton.free) {
4793 bleedx += 4 * direction / realtexdetail;
4795 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4797 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4800 bleedy -= 4 / realtexdetail;
4802 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4804 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4809 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4810 righthandmorphness = targetrighthandmorphness;
4811 righthandmorphstart = righthandmorphend;
4812 } else if (righthandmorphness > targetrighthandmorphness) {
4813 righthandmorphness -= multiplier * 4;
4814 } else if (righthandmorphness < targetrighthandmorphness) {
4815 righthandmorphness += multiplier * 4;
4818 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4819 lefthandmorphness = targetlefthandmorphness;
4820 lefthandmorphstart = lefthandmorphend;
4821 } else if (lefthandmorphness > targetlefthandmorphness) {
4822 lefthandmorphness -= multiplier * 4;
4823 } else if (lefthandmorphness < targetlefthandmorphness) {
4824 lefthandmorphness += multiplier * 4;
4827 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4828 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4829 tailmorphness = targettailmorphness;
4830 tailmorphstart = tailmorphend;
4831 } else if (tailmorphness > targettailmorphness) {
4832 tailmorphness -= multiplier * 10;
4833 } else if (tailmorphness < targettailmorphness) {
4834 tailmorphness += multiplier * 10;
4838 if (creature == wolftype) {
4839 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4840 tailmorphness = targettailmorphness;
4841 tailmorphstart = tailmorphend;
4842 } else if (tailmorphness > targettailmorphness) {
4843 tailmorphness -= multiplier * 2;
4844 } else if (tailmorphness < targettailmorphness) {
4845 tailmorphness += multiplier * 2;
4849 if (headmorphend == 3 || headmorphstart == 3) {
4850 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4851 headmorphness = targetheadmorphness;
4852 headmorphstart = headmorphend;
4853 } else if (headmorphness > targetheadmorphness) {
4854 headmorphness -= multiplier * 7;
4855 } else if (headmorphness < targetheadmorphness) {
4856 headmorphness += multiplier * 7;
4858 } else if (headmorphend == 5 || headmorphstart == 5) {
4859 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4860 headmorphness = targetheadmorphness;
4861 headmorphstart = headmorphend;
4862 } else if (headmorphness > targetheadmorphness) {
4863 headmorphness -= multiplier * 10;
4864 } else if (headmorphness < targetheadmorphness) {
4865 headmorphness += multiplier * 10;
4868 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4869 headmorphness = targetheadmorphness;
4870 headmorphstart = headmorphend;
4871 } else if (headmorphness > targetheadmorphness) {
4872 headmorphness -= multiplier * 4;
4873 } else if (headmorphness < targetheadmorphness) {
4874 headmorphness += multiplier * 4;
4878 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4879 chestmorphness = targetchestmorphness;
4880 chestmorphstart = chestmorphend;
4881 } else if (chestmorphness > targetchestmorphness) {
4882 chestmorphness -= multiplier;
4883 } else if (chestmorphness < targetchestmorphness) {
4884 chestmorphness += multiplier;
4887 if (dead != 2 && howactive <= typesleeping) {
4888 if (chestmorphstart == 0 && chestmorphend == 0) {
4890 targetchestmorphness = 1;
4893 if (chestmorphstart != 0 && chestmorphend != 0) {
4895 targetchestmorphness = 1;
4897 if (environment == snowyenvironment) {
4900 if (skeleton.free) {
4901 footvel = skeleton.specialforward[0] * -1;
4902 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4904 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4905 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4907 if (animTarget == sleepanim) {
4908 footvel = DoRotation(footvel, 0, 90, 0);
4910 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4914 if (!dead && howactive < typesleeping) {
4915 blinkdelay -= multiplier * 2;
4916 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4918 targetheadmorphness = 1;
4920 blinkdelay = (float)(abs(Random() % 40)) / 5;
4922 if (headmorphstart == 3 && headmorphend == 3) {
4924 targetheadmorphness = 1;
4929 twitchdelay -= multiplier * 1.5;
4930 if (animTarget != hurtidleanim) {
4931 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4933 targetheadmorphness = 1;
4935 twitchdelay = (float)(abs(Random() % 40)) / 5;
4937 if (headmorphstart == 5 && headmorphend == 5) {
4939 targetheadmorphness = 1;
4943 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4944 twitchdelay3 -= multiplier * 1;
4945 if (Random() % 2 == 0) {
4946 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4947 righthandmorphness = 0;
4948 targetrighthandmorphness = 1;
4949 righthandmorphend = 1;
4950 if (Random() % 2 == 0) {
4951 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4954 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4955 righthandmorphness = 0;
4956 targetrighthandmorphness = 1;
4957 righthandmorphend = 0;
4960 if (Random() % 2 == 0) {
4961 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4962 lefthandmorphness = 0;
4963 targetlefthandmorphness = 1;
4964 lefthandmorphend = 1;
4965 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4967 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4968 lefthandmorphness = 0;
4969 targetlefthandmorphness = 1;
4970 lefthandmorphend = 0;
4976 if (creature == rabbittype) {
4977 if (howactive < typesleeping) {
4978 twitchdelay2 -= multiplier * 1.5;
4980 twitchdelay2 -= multiplier * 0.5;
4982 if (howactive <= typesleeping) {
4983 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4985 targettailmorphness = 1;
4987 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4989 if (tailmorphstart == 1 && tailmorphend == 1) {
4991 targettailmorphness = 1;
4994 if (tailmorphstart == 2 && tailmorphend == 2) {
4996 targettailmorphness = 1;
5003 if (creature == wolftype) {
5004 twitchdelay2 -= multiplier * 1.5;
5005 if (tailmorphend != 0) {
5006 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5008 targettailmorphness = 1;
5013 if (tailmorphend != 5) {
5014 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5016 targettailmorphness = 1;
5021 if (twitchdelay2 <= 0) {
5022 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5024 targettailmorphness = 1;
5027 if (tailmorphstart == 1 && tailmorphend == 1) {
5029 targettailmorphness = 1;
5032 if (tailmorphstart == 2 && tailmorphend == 2) {
5034 targettailmorphness = 1;
5037 if (tailmorphstart == 3 && tailmorphend == 3) {
5039 targettailmorphness = 1;
5042 if (tailmorphstart == 4 && tailmorphend == 4) {
5044 targettailmorphness = 1;
5051 unconscioustime = 0;
5054 if (dead == 1 || howactive == typesleeping) {
5055 unconscioustime += multiplier;
5056 //If unconscious, close eyes and mouth
5057 if (righthandmorphend != 0) {
5058 righthandmorphness = 0;
5060 righthandmorphend = 0;
5061 targetrighthandmorphness = 1;
5063 if (lefthandmorphend != 0) {
5064 lefthandmorphness = 0;
5066 lefthandmorphend = 0;
5067 targetlefthandmorphness = 1;
5069 if (headmorphend != 3 && headmorphend != 5) {
5073 targetheadmorphness = 1;
5076 if (howactive > typesleeping) {
5079 if (bloodtoggle && !bled) {
5080 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5081 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5082 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5083 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5087 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5093 if (dead == 2 || howactive > typesleeping) {
5094 //If dead, open mouth and hands
5095 if (righthandmorphend != 0) {
5096 righthandmorphness = 0;
5098 righthandmorphend = 0;
5099 targetrighthandmorphness = 1;
5101 if (lefthandmorphend != 0) {
5102 lefthandmorphness = 0;
5104 lefthandmorphend = 0;
5105 targetlefthandmorphness = 1;
5107 if (headmorphend != 2) {
5111 targetheadmorphness = 1;
5114 if (stunned > 0 && !dead && headmorphend != 2) {
5115 if (headmorphend != 4) {
5119 targetheadmorphness = 1;
5122 if (damage > damagetolerance && !dead) {
5125 unconscioustime = 0;
5127 if (creature == wolftype) {
5128 award_bonus(0, Wolfbonus);
5133 if (weaponactive != -1) {
5134 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5135 weapons[weaponids[0]].velocity.x += .01;
5138 weaponids[0] = weaponids[num_weapons];
5139 if (weaponstuck == num_weapons) {
5144 for (unsigned i = 0; i < Person::players.size(); i++) {
5145 Person::players[i]->wentforweapon = 0;
5149 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5158 damage -= multiplier * 13;
5159 permanentdamage -= multiplier * 4;
5160 if (isIdle() || isCrouch()) {
5161 permanentdamage -= multiplier * 4;
5167 if (permanentdamage < 0) {
5168 permanentdamage = 0;
5170 if (superpermanentdamage < 0) {
5171 superpermanentdamage = 0;
5173 if (permanentdamage < superpermanentdamage) {
5174 permanentdamage = superpermanentdamage;
5176 if (damage < permanentdamage) {
5177 damage = permanentdamage;
5179 if (dead == 1 && damage < damagetolerance) {
5183 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5184 skeleton.joints[i].velocity = 0;
5187 if (permanentdamage > damagetolerance && dead != 2) {
5190 if (weaponactive != -1) {
5191 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5192 weapons[weaponids[0]].velocity.x += .01;
5195 weaponids[0] = weaponids[num_weapons];
5196 if (weaponstuck == num_weapons) {
5201 for (unsigned i = 0; i < Person::players.size(); i++) {
5202 Person::players[i]->wentforweapon = 0;
5208 if (!dead && creature == wolftype) {
5209 award_bonus(0, Wolfbonus);
5212 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5213 award_bonus(id, touchofdeath);
5215 if (id != 0 && unconscioustime > .1) {
5223 emit_sound_at(breaksound, coords);
5226 if (skeleton.free == 1) {
5228 pause_sound(whooshsound);
5232 //If knocked over, open hands and close mouth
5233 if (righthandmorphend != 0) {
5234 righthandmorphness = 0;
5236 righthandmorphend = 0;
5237 targetrighthandmorphness = 1;
5239 if (lefthandmorphend != 0) {
5240 lefthandmorphness = 0;
5242 lefthandmorphend = 0;
5243 targetlefthandmorphness = 1;
5245 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5246 if (headmorphend != 0) {
5250 targetheadmorphness = 1;
5254 skeleton.DoGravity(&scale);
5256 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5257 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5258 award_bonus(id, deepimpact);
5260 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5264 if (!skeleton.joints.empty()) {
5265 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5266 average += skeleton.joints[j].position;
5268 average /= skeleton.joints.size();
5269 coords += average * scale;
5270 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5271 skeleton.joints[j].position -= average;
5273 average /= multiplier;
5277 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5278 velocity += skeleton.joints[i].velocity * scale;
5280 velocity /= skeleton.joints.size();
5282 if (!isnormal(velocity.x) && velocity.x) {
5286 if (findLength(&average) < 10 && dead && skeleton.free) {
5287 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5288 if (skeleton.longdead > 2000) {
5289 if (skeleton.longdead > 6000) {
5291 pause_sound(whooshsound);
5297 if (dead == 2 && bloodloss < damagetolerance) {
5299 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5301 if (bloodtoggle && !bled) {
5302 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5303 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5304 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5305 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5306 float size = .2 * 1.2;
5309 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5314 if (dead == 2 && bloodloss >= damagetolerance) {
5316 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5317 if (bleeding <= 0) {
5320 if (bloodtoggle && !bled) {
5321 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5322 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5323 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5324 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5328 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5336 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5337 bool canrecover = 1;
5338 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5339 startpoint = coords;
5342 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5345 if (velocity.y < -30) {
5348 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5349 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5350 colviewer = startpoint;
5351 coltarget = endpoint;
5352 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5362 terrainnormal = jointPos(groin) - jointPos(abdomen);
5363 if (joint(groin).locked && joint(abdomen).locked) {
5364 terrainnormal = jointPos(groin) - jointPos(abdomen);
5365 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5367 if (joint(abdomen).locked && joint(neck).locked) {
5368 terrainnormal = jointPos(abdomen) - jointPos(neck);
5369 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5371 if (joint(groin).locked && joint(neck).locked) {
5372 terrainnormal = jointPos(groin) - jointPos(neck);
5373 middle = (jointPos(groin) + jointPos(neck)) / 2;
5375 Normalise(&terrainnormal);
5377 targetyaw = -asin(0 - terrainnormal.x);
5378 targetyaw *= 360 / 6.28;
5379 if (terrainnormal.z < 0) {
5380 targetyaw = 180 - targetyaw;
5385 animTarget = flipanim;
5386 crouchtogglekeydown = 1;
5391 animCurrent = tempanim;
5395 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5396 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5397 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5402 if (findLength(&average) < 10 && !dead && skeleton.free) {
5403 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5404 if (skeleton.longdead > (damage + 500) * 1.5) {
5406 pause_sound(whooshsound);
5413 terrainnormal = jointPos(groin) - jointPos(abdomen);
5414 if (joint(groin).locked && joint(abdomen).locked) {
5415 terrainnormal = jointPos(groin) - jointPos(abdomen);
5416 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5418 if (joint(abdomen).locked && joint(neck).locked) {
5419 terrainnormal = jointPos(abdomen) - jointPos(neck);
5420 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5422 if (joint(groin).locked && joint(neck).locked) {
5423 terrainnormal = jointPos(groin) - jointPos(neck);
5424 middle = (jointPos(groin) + jointPos(neck)) / 2;
5426 Normalise(&terrainnormal);
5428 targetyaw = -asin(0 - terrainnormal.x);
5429 targetyaw *= 360 / 6.28;
5430 if (terrainnormal.z < 0) {
5431 targetyaw = 180 - targetyaw;
5435 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5437 if (skeleton.forward.y < 0) {
5438 animTarget = getupfrombackanim;
5442 if (skeleton.forward.y > -.3) {
5443 animTarget = getupfromfrontanim;
5451 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5452 animTarget = rollanim;
5453 targetyaw = lookyaw;
5457 if (forwardkeydown) {
5466 if (forwardkeydown) {
5474 if (!leftkeydown && !rightkeydown) {
5482 if (abs(targettilt2) > 50) {
5485 animCurrent = tempanim;
5488 tilt2 = targettilt2;
5490 if (middle.y > 0 && animTarget != rollanim) {
5491 targetoffset.y = middle.y + 1;
5494 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5495 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5496 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5503 if (num_weapons > 0) {
5504 if (weapons[0].getType() == staff) {
5508 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5509 if (velocity.y > -30) {
5511 tempvelocity = velocity;
5512 Normalise(&tempvelocity);
5513 targetyaw = -asin(0 - tempvelocity.x);
5514 targetyaw *= 360 / 6.28;
5515 if (velocity.z < 0) {
5516 targetyaw = 180 - targetyaw;
5521 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5522 animTarget = rollanim;
5525 animTarget = backhandspringanim;
5531 emit_sound_at(movewhooshsound, coords, 128.);
5533 animCurrent = animTarget;
5534 frameCurrent = frameTarget - 1;
5546 if (skeleton.freefall == 0) {
5551 if (aitype != passivetype || skeleton.free == 1) {
5552 if (findLengthfast(&velocity) > .1) {
5553 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5554 if (Object::objects[i]->type == firetype) {
5555 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) {
5557 if (!Object::objects[i]->onfire) {
5558 emit_sound_at(firestartsound, Object::objects[i]->position);
5560 Object::objects[i]->onfire = 1;
5563 if (Object::objects[i]->onfire) {
5569 if (Object::objects[i]->type == bushtype) {
5570 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) {
5572 if (!Object::objects[i]->onfire) {
5573 emit_sound_at(firestartsound, Object::objects[i]->position);
5575 Object::objects[i]->onfire = 1;
5579 if (Object::objects[i]->onfire) {
5583 if (Object::objects[i]->messedwith <= 0) {
5587 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5590 addEnvSound(coords, 4 * findLength(&velocity));
5594 if (environment == grassyenvironment) {
5595 howmany = findLength(&velocity) * 4;
5597 if (environment == snowyenvironment) {
5598 howmany = findLength(&velocity) * 2;
5601 if (environment != desertenvironment) {
5602 for (int j = 0; j < howmany; j++) {
5603 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5604 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5605 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5608 pos.x += float(abs(Random() % 100) - 50) / 200;
5609 pos.y += float(abs(Random() % 100) - 50) / 200;
5610 pos.z += float(abs(Random() % 100) - 50) / 200;
5611 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);
5612 Sprite::setLastSpriteSpecial(1);
5616 howmany = findLength(&velocity) * 4;
5618 if (environment == snowyenvironment) {
5619 for (int j = 0; j < howmany; j++) {
5620 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5621 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5622 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5625 pos.x += float(abs(Random() % 100) - 50) / 200;
5626 pos.y += float(abs(Random() % 100) - 50) / 200;
5627 pos.z += float(abs(Random() % 100) - 50) / 200;
5628 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5629 Sprite::setLastSpriteSpecial(2);
5634 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5635 Object::objects[i]->roty += velocity.z * multiplier * 6;
5636 Object::objects[i]->messedwith = .5;
5640 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5641 if (Object::objects[i]->pitch == 0) {
5644 tempcoord = coords - Object::objects[i]->position;
5645 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5646 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5647 tempcoord += Object::objects[i]->position;
5649 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) {
5650 if (Object::objects[i]->messedwith <= 0) {
5654 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5657 addEnvSound(coords, 4 * findLength(&velocity));
5661 if (environment == grassyenvironment) {
5662 howmany = findLength(&velocity) * 4;
5664 if (environment == snowyenvironment) {
5665 howmany = findLength(&velocity) * 2;
5668 if (environment != desertenvironment) {
5669 for (int j = 0; j < howmany; j++) {
5670 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5671 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5672 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5674 pos += velocity * .1;
5676 pos.x += float(abs(Random() % 100) - 50) / 150;
5677 pos.y += float(abs(Random() % 100) - 50) / 150;
5678 pos.z += float(abs(Random() % 100) - 50) / 150;
5679 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);
5680 Sprite::setLastSpriteSpecial(1);
5684 howmany = findLength(&velocity) * 4;
5686 if (environment == snowyenvironment) {
5687 for (int j = 0; j < howmany; j++) {
5688 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5689 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5690 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5692 pos += velocity * .1;
5694 pos.x += float(abs(Random() % 100) - 50) / 150;
5695 pos.y += float(abs(Random() % 100) - 50) / 150;
5696 pos.z += float(abs(Random() % 100) - 50) / 150;
5697 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5698 Sprite::setLastSpriteSpecial(2);
5703 Object::objects[i]->messedwith = .5;
5710 if (!skeleton.free) {
5713 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5717 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5721 if (Tutorial::active && id != 0) {
5724 if (play && aitype != playercontrolled) {
5725 int whichsound = -1;
5726 if (speechdelay <= 0) {
5727 unsigned int i = abs(Random() % 4);
5729 whichsound = PersonType::types[creature].soundsTalk[i];
5734 if (whichsound != -1) {
5735 emit_sound_at(whichsound, coords);
5739 if (animTarget == staggerbackhighanim) {
5742 if (animTarget == staggerbackhardanim) {
5745 staggerdelay -= multiplier;
5746 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5749 if (velocity.y < -30 && animTarget == jumpdownanim) {
5752 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5753 animTarget = getIdle();
5757 weaponmissdelay -= multiplier;
5758 highreversaldelay -= multiplier;
5759 lowreversaldelay -= multiplier;
5760 lastcollide -= multiplier;
5761 skiddelay -= multiplier;
5762 if (!isnormal(velocity.x) && velocity.x) {
5765 if (!isnormal(targettilt) && targettilt) {
5768 if (!isnormal(targettilt2) && targettilt2) {
5771 if (!isnormal(targetyaw) && targetyaw) {
5775 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5776 //open hands and close mouth
5777 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5778 righthandmorphness = 0;
5779 righthandmorphend = 0;
5780 targetrighthandmorphness = 1;
5783 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5784 lefthandmorphness = 0;
5785 lefthandmorphend = 0;
5786 targetlefthandmorphness = 1;
5789 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5792 targetheadmorphness = 1;
5796 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) {
5797 //open hands and mouth
5798 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5799 righthandmorphness = 0;
5800 righthandmorphend = 0;
5801 targetrighthandmorphness = 1;
5804 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5805 lefthandmorphness = 0;
5806 lefthandmorphend = 0;
5807 targetlefthandmorphness = 1;
5810 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5813 targetheadmorphness = 1;
5817 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5818 //close hands and mouth
5819 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5820 righthandmorphness = 0;
5821 righthandmorphend = 1;
5822 targetrighthandmorphness = 1;
5825 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5826 lefthandmorphness = 0;
5827 lefthandmorphend = 1;
5828 targetlefthandmorphness = 1;
5831 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5834 targetheadmorphness = 1;
5838 if (animTarget == spinkickanim ||
5839 animTarget == staffspinhitreversalanim ||
5840 animTarget == staffspinhitreversedanim ||
5841 animTarget == staffhitreversalanim ||
5842 animTarget == staffhitreversedanim ||
5843 animTarget == hurtidleanim ||
5844 animTarget == winduppunchanim ||
5845 animTarget == swordslashreversalanim ||
5846 animTarget == swordslashreversedanim ||
5847 animTarget == knifeslashreversalanim ||
5848 animTarget == knifeslashreversedanim ||
5849 animTarget == knifethrowanim ||
5850 animTarget == knifefollowanim ||
5851 animTarget == knifefollowedanim ||
5852 animTarget == killanim ||
5853 animTarget == dropkickanim ||
5854 animTarget == upunchanim ||
5855 animTarget == knifeslashstartanim ||
5856 animTarget == swordslashanim ||
5857 animTarget == staffhitanim ||
5858 animTarget == staffspinhitanim ||
5859 animTarget == staffgroundsmashanim ||
5860 animTarget == spinkickreversalanim ||
5861 animTarget == sweepreversalanim ||
5862 animTarget == lowkickanim ||
5863 animTarget == sweepreversedanim ||
5864 animTarget == rabbitkickreversalanim ||
5865 animTarget == rabbitkickreversedanim ||
5866 animTarget == jumpreversalanim ||
5867 animTarget == jumpreversedanim) {
5868 //close hands and yell
5869 if (righthandmorphend != 1 &&
5870 righthandmorphness == targetrighthandmorphness) {
5871 righthandmorphness = 0;
5872 righthandmorphend = 1;
5873 targetrighthandmorphness = 1;
5876 if (lefthandmorphend != 1 &&
5877 lefthandmorphness == targetlefthandmorphness) {
5878 lefthandmorphness = 0;
5879 lefthandmorphend = 1;
5880 targetlefthandmorphness = 1;
5883 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5886 targetheadmorphness = 1;
5893 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5894 (victim->aitype != searchtype) && (aitype != passivetype) &&
5895 (aitype != searchtype) && (victim->id < Person::players.size())) {
5896 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5900 if (!dead && animTarget != hurtidleanim) {
5901 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5902 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5905 targetheadmorphness = 1;
5910 if (weaponactive != -1) {
5911 if (weapons[weaponids[weaponactive]].getType() != staff) {
5912 righthandmorphstart = 1;
5913 righthandmorphend = 1;
5915 if (weapons[weaponids[weaponactive]].getType() == staff) {
5916 righthandmorphstart = 2;
5917 righthandmorphend = 2;
5919 targetrighthandmorphness = 1;
5922 terrainnormal = terrain.getNormal(coords.x, coords.z);
5924 if (Animation::animations[animTarget].attack != reversal) {
5925 if (!isnormal(coords.x)) {
5934 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5935 facing = flatfacing;
5936 ReflectVector(&facing, terrainnormal);
5940 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5942 targettilt2 = -facing.y * 20;
5948 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
5951 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5952 flatvelocity = velocity;
5954 flatvelspeed = findLength(&flatvelocity);
5955 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5956 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5957 if (velocity.y < 0) {
5960 if (velocity.y < 0) {
5963 if (targettilt > 25) {
5966 if (targettilt < -25) {
5971 if (targettilt2 > 45) {
5974 if (targettilt2 < -45) {
5977 if (abs(tilt2 - targettilt2) < multiplier * 400) {
5978 tilt2 = targettilt2;
5979 } else if (tilt2 > targettilt2) {
5980 tilt2 -= multiplier * 400;
5981 } else if (tilt2 < targettilt2) {
5982 tilt2 += multiplier * 400;
5984 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5993 if (!isnormal(targettilt) && targettilt) {
5996 if (!isnormal(targettilt2) && targettilt2) {
6001 if (animTarget == rabbittackleanim) {
6002 velocity += facing * multiplier * speed * 700 * scale;
6003 velspeed = findLength(&velocity);
6004 if (velspeed > speed * 65 * scale) {
6005 velocity /= velspeed;
6006 velspeed = speed * 65 * scale;
6007 velocity *= velspeed;
6009 velocity.y += gravity * multiplier * 20;
6010 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6011 velspeed = findLength(&velocity);
6012 velocity = flatfacing * velspeed;
6014 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6015 if (isRun() || animTarget == rabbitkickanim) {
6016 velocity += facing * multiplier * speed * 700 * scale;
6017 velspeed = findLength(&velocity);
6018 if (velspeed > speed * 45 * scale) {
6019 velocity /= velspeed;
6020 velspeed = speed * 45 * scale;
6021 velocity *= velspeed;
6023 velocity.y += gravity * multiplier * 20;
6024 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6025 velspeed = findLength(&velocity);
6026 if (velspeed < speed * 30 * scale) {
6027 velspeed = speed * 30 * scale;
6029 velocity = flatfacing * velspeed;
6031 } else if (isRun()) {
6032 velocity += facing * multiplier * speed * 700 * scale;
6033 velspeed = findLength(&velocity);
6034 if (creature == rabbittype) {
6035 if (velspeed > speed * 55 * scale) {
6036 velocity /= velspeed;
6037 velspeed = speed * 55 * scale;
6038 velocity *= velspeed;
6041 if (creature == wolftype) {
6042 if (velspeed > speed * 75 * scale) {
6043 velocity /= velspeed;
6044 velspeed = speed * 75 * scale;
6045 velocity *= velspeed;
6048 velocity.y += gravity * multiplier * 20;
6049 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6050 velspeed = findLength(&velocity);
6051 velocity = flatfacing * velspeed;
6054 if (animTarget == rollanim && targetFrame().label != 6) {
6055 velocity += facing * multiplier * speed * 700 * scale;
6056 velspeed = findLength(&velocity);
6057 if (velspeed > speed * 45 * scale) {
6058 velocity /= velspeed;
6059 velspeed = speed * 45 * scale;
6060 velocity *= velspeed;
6062 velocity.y += gravity * multiplier * 20;
6063 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6064 velspeed = findLength(&velocity);
6065 velocity = flatfacing * velspeed;
6068 if (animTarget == sneakanim || animTarget == walkanim) {
6069 velocity += facing * multiplier * speed * 700 * scale;
6070 velspeed = findLength(&velocity);
6071 if (velspeed > speed * 12 * scale) {
6072 velocity /= velspeed;
6073 velspeed = speed * 12 * scale;
6074 velocity *= velspeed;
6076 velocity.y += gravity * multiplier * 20;
6077 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6078 velspeed = findLength(&velocity);
6079 velocity = flatfacing * velspeed;
6082 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6083 velocity += facing * multiplier * speed * 700 * scale;
6084 velspeed = findLength(&velocity);
6085 if (velspeed > speed * 2 * scale) {
6086 velocity /= velspeed;
6087 velspeed = speed * 2 * scale;
6088 velocity *= velspeed;
6090 velocity.y += gravity * multiplier * 20;
6091 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6092 velspeed = findLength(&velocity);
6093 velocity = flatfacing * velspeed;
6096 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6097 velocity -= facing * multiplier * speed * 700 * scale;
6098 velspeed = findLength(&velocity);
6099 if (velspeed > speed * 2 * scale) {
6100 velocity /= velspeed;
6101 velspeed = speed * 2 * scale;
6102 velocity *= velspeed;
6104 velocity.y += gravity * multiplier * 20;
6105 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6106 velspeed = findLength(&velocity);
6107 velocity = flatfacing * velspeed * -1;
6110 if (animTarget == fightsidestep) {
6111 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6112 velspeed = findLength(&velocity);
6113 if (velspeed > speed * 12 * scale) {
6114 velocity /= velspeed;
6115 velspeed = speed * 12 * scale;
6116 velocity *= velspeed;
6118 velocity.y += gravity * multiplier * 20;
6119 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6120 velspeed = findLength(&velocity);
6121 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6124 if (animTarget == staggerbackhighanim) {
6125 coords -= facing * multiplier * speed * 16 * scale;
6128 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6129 coords -= facing * multiplier * speed * 20 * scale;
6133 if (animTarget == backhandspringanim) {
6134 //coords-=facing*multiplier*50*scale;
6135 velocity += facing * multiplier * speed * 700 * scale * -1;
6136 velspeed = findLength(&velocity);
6137 if (velspeed > speed * 50 * scale) {
6138 velocity /= velspeed;
6139 velspeed = speed * 50 * scale;
6140 velocity *= velspeed;
6142 velocity.y += gravity * multiplier * 20;
6143 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6144 velspeed = findLength(&velocity);
6145 velocity = flatfacing * velspeed * -1;
6147 if (animTarget == dodgebackanim) {
6148 //coords-=facing*multiplier*50*scale;
6149 velocity += facing * multiplier * speed * 700 * scale * -1;
6150 velspeed = findLength(&velocity);
6151 if (velspeed > speed * 60 * scale) {
6152 velocity /= velspeed;
6153 velspeed = speed * 60 * scale;
6154 velocity *= velspeed;
6156 velocity.y += gravity * multiplier * 20;
6157 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6158 velspeed = findLength(&velocity);
6159 velocity = flatfacing * velspeed * -1;
6162 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6163 velspeed = findLength(&velocity);
6166 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6167 velocity.y += gravity * multiplier;
6170 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6171 coords += velocity * multiplier;
6174 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6175 if (isFlip() && targetFrame().label == 7) {
6179 if (animTarget == jumpupanim) {
6181 animTarget = getIdle();
6188 pause_sound(whooshsound);
6189 OPENAL_SetVolume(channels[whooshsound], 0);
6192 if (animTarget == jumpdownanim || isFlip()) {
6196 animTarget = getLanding();
6197 emit_sound_at(landsound, coords, 128.);
6200 addEnvSound(coords);
6205 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6206 coords.y += gravity * multiplier * 2;
6208 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6209 coords.y = terrain.getHeight(coords.x, coords.z);
6213 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)) {
6214 velspeed = findLength(&velocity);
6216 if (velspeed < multiplier * 300 * scale) {
6219 velocity -= velocity / velspeed * multiplier * 300 * scale;
6221 if (velspeed > 5 && (isLanding() || isLandhard())) {
6222 skiddingdelay += multiplier;
6223 if (skiddelay <= 0) {
6224 FootLand(leftfoot, .5);
6225 FootLand(rightfoot, .5);
6234 velspeed = findLength(&velocity);
6236 if (velspeed > 5 && (isLanding() || isLandhard())) {
6237 skiddingdelay += multiplier;
6238 if (skiddelay <= 0) {
6239 FootLand(leftfoot, .5);
6240 FootLand(rightfoot, .5);
6248 if (skiddingdelay < 0) {
6249 skiddingdelay += multiplier;
6251 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6253 if (!onterrain || environment == grassyenvironment) {
6254 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6256 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6260 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6261 terrainnormal = victim->coords - coords;
6262 Normalise(&terrainnormal);
6263 targetyaw = -asin(0 - terrainnormal.x);
6264 targetyaw *= 360 / 6.28;
6265 if (terrainnormal.z < 0) {
6266 targetyaw = 180 - targetyaw;
6268 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6271 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6272 targetyaw = victim->targetyaw;
6274 if (animTarget == rabbittacklinganim) {
6275 coords = victim->coords;
6278 skeleton.oldfree = skeleton.free;
6282 midterrain.x = terrain.size * terrain.scale / 2;
6283 midterrain.z = terrain.size * terrain.scale / 2;
6284 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6286 tempposit = coords - midterrain;
6288 Normalise(&tempposit);
6289 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6290 coords.x = tempposit.x + midterrain.x;
6291 coords.z = tempposit.z + midterrain.z;
6296 * inverse kinematics helper function
6298 void IKHelper(Person* p, float interp)
6300 XYZ point, change, change2;
6301 float heightleft, heightright;
6303 // TODO: implement localToWorld and worldToLocal
6304 // but keep in mind it won't be the same math if player is ragdolled or something
6305 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6306 // then comb through code for places where to use it
6308 // point = localToWorld(jointPos(leftfoot))
6309 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6310 // adjust height of foot
6311 heightleft = terrain.getHeight(point.x, point.z) + .04;
6312 point.y = heightleft;
6313 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6314 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6315 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6316 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6317 // move ankle along with foot
6318 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6319 // average knee pos between old and new pos
6320 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6322 // do same as above for right leg
6323 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6324 heightright = terrain.getHeight(point.x, point.z) + .04;
6325 point.y = heightright;
6326 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6327 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6328 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6329 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6330 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6332 // fix up skeleton now that we've moved body parts?
6333 p->skeleton.DoConstraints(&p->coords, &p->scale);
6340 int Person::DrawSkeleton()
6342 int oldplayerdetail;
6343 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6344 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6354 glAlphaFunc(GL_GREATER, 0.0001);
6356 float terrainheight;
6358 if (!isnormal(yaw)) {
6361 if (!isnormal(tilt)) {
6364 if (!isnormal(tilt2)) {
6367 oldplayerdetail = playerdetail;
6369 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6372 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6375 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6381 if (playerdetail != oldplayerdetail) {
6383 normalsupdatedelay = 0;
6385 static float updatedelaychange;
6386 static float morphness;
6387 static float framemult;
6389 skeleton.FindForwards();
6390 if (howactive == typesittingwall) {
6391 skeleton.specialforward[1] = 0;
6392 skeleton.specialforward[1].z = 1;
6398 static int weaponattachmuscle;
6399 static int weaponrotatemuscle;
6400 static XYZ weaponpoint;
6401 static int start, endthing;
6402 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6403 if (!isSleeping() && !isSitting()) {
6404 // TODO: give these meaningful names
6405 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6406 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6408 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6410 if (creature == wolftype) {
6415 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6416 IKHelper(this, target);
6417 if (creature == wolftype) {
6418 IKHelper(this, target);
6422 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6423 IKHelper(this, 1 - target);
6424 if (creature == wolftype) {
6425 IKHelper(this, 1 - target);
6430 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())) {
6433 targetheadyaw = -targetyaw;
6434 targetheadpitch = 0;
6435 if (Animation::animations[animTarget].attack == 3) {
6436 targetheadyaw += 180;
6439 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6440 skeleton.drawmodel.vertex[i] = 0;
6441 skeleton.drawmodel.vertex[i].y = 999;
6443 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6444 skeleton.drawmodellow.vertex[i] = 0;
6445 skeleton.drawmodellow.vertex[i].y = 999;
6447 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6448 skeleton.drawmodelclothes.vertex[i] = 0;
6449 skeleton.drawmodelclothes.vertex[i].y = 999;
6451 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6452 // convenience renames
6453 const int p1 = skeleton.muscles[i].parent1->label;
6454 const int p2 = skeleton.muscles[i].parent2->label;
6456 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6461 if (p1 == righthand || p2 == righthand) {
6462 morphness = righthandmorphness;
6463 start = righthandmorphstart;
6464 endthing = righthandmorphend;
6466 if (p1 == lefthand || p2 == lefthand) {
6467 morphness = lefthandmorphness;
6468 start = lefthandmorphstart;
6469 endthing = lefthandmorphend;
6471 if (p1 == head || p2 == head) {
6472 morphness = headmorphness;
6473 start = headmorphstart;
6474 endthing = headmorphend;
6476 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6477 morphness = chestmorphness;
6478 start = chestmorphstart;
6479 endthing = chestmorphend;
6481 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6482 morphness = tailmorphness;
6483 start = tailmorphstart;
6484 endthing = tailmorphend;
6487 skeleton.FindRotationMuscle(i, animTarget);
6489 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6490 glMatrixMode(GL_MODELVIEW);
6493 if (!skeleton.free) {
6494 glRotatef(tilt2, 1, 0, 0);
6496 if (!skeleton.free) {
6497 glRotatef(tilt, 0, 0, 1);
6500 glTranslatef(mid.x, mid.y, mid.z);
6502 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6503 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6505 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6506 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6508 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6509 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6511 if (playerdetail || skeleton.free == 3) {
6512 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6513 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6514 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6515 glMatrixMode(GL_MODELVIEW);
6517 if (p1 == abdomen || p2 == abdomen) {
6518 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(1).x,
6519 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(1).y,
6520 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(1).z);
6522 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6523 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(2).x,
6524 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(2).y,
6525 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(2).z);
6527 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6528 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(3).x,
6529 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(3).y,
6530 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(3).z);
6532 if (p1 == head || p2 == head) {
6533 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(0).x,
6534 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(0).y,
6535 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(0).z);
6537 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6538 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6539 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6540 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6544 if (!playerdetail || skeleton.free == 3) {
6545 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6546 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6547 glMatrixMode(GL_MODELVIEW);
6549 if (p1 == abdomen || p2 == abdomen) {
6550 glTranslatef(v0.x * getProportionXYZ(1).x,
6551 v0.y * getProportionXYZ(1).y,
6552 v0.z * getProportionXYZ(1).z);
6554 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6555 glTranslatef(v0.x * getProportionXYZ(2).x,
6556 v0.y * getProportionXYZ(2).y,
6557 v0.z * getProportionXYZ(2).z);
6559 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6560 glTranslatef(v0.x * getProportionXYZ(3).x,
6561 v0.y * getProportionXYZ(3).y,
6562 v0.z * getProportionXYZ(3).z);
6564 if (p1 == head || p2 == head) {
6565 glTranslatef(v0.x * getProportionXYZ(0).x,
6566 v0.y * getProportionXYZ(0).y,
6567 v0.z * getProportionXYZ(0).z);
6570 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6571 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6572 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6573 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6579 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6580 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6582 glMatrixMode(GL_MODELVIEW);
6585 if (!skeleton.free) {
6586 glRotatef(tilt2, 1, 0, 0);
6588 if (!skeleton.free) {
6589 glRotatef(tilt, 0, 0, 1);
6591 glTranslatef(mid.x, mid.y, mid.z);
6592 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6593 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6595 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6596 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6598 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6599 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6601 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6602 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6603 glMatrixMode(GL_MODELVIEW);
6605 if (p1 == abdomen || p2 == abdomen) {
6606 glTranslatef(v0.x * getProportionXYZ(1).x,
6607 v0.y * getProportionXYZ(1).y,
6608 v0.z * getProportionXYZ(1).z);
6610 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6611 glTranslatef(v0.x * getProportionXYZ(2).x,
6612 v0.y * getProportionXYZ(2).y,
6613 v0.z * getProportionXYZ(2).z);
6615 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6616 glTranslatef(v0.x * getProportionXYZ(3).x,
6617 v0.y * getProportionXYZ(3).y,
6618 v0.z * getProportionXYZ(3).z);
6620 if (p1 == head || p2 == head) {
6621 glTranslatef(v0.x * getProportionXYZ(0).x,
6622 v0.y * getProportionXYZ(0).y,
6623 v0.z * getProportionXYZ(0).z);
6625 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6626 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6627 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6628 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6633 updatedelay = 1 + (float)(Random() % 100) / 1000;
6635 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6636 normalsupdatedelay = 1;
6637 if (playerdetail || skeleton.free == 3) {
6638 skeleton.drawmodel.CalculateNormals(0);
6640 if (!playerdetail || skeleton.free == 3) {
6641 skeleton.drawmodellow.CalculateNormals(0);
6643 if (skeleton.clothes) {
6644 skeleton.drawmodelclothes.CalculateNormals(0);
6647 if (playerdetail || skeleton.free == 3) {
6648 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6650 if (!playerdetail || skeleton.free == 3) {
6651 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6653 if (skeleton.clothes) {
6654 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6659 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6660 if (updatedelaychange > -realmultiplier * 30) {
6661 updatedelaychange = -realmultiplier * 30;
6663 if (updatedelaychange > -framemult * 4) {
6664 updatedelaychange = -framemult * 4;
6666 if (skeleton.free == 1) {
6667 updatedelaychange *= 6;
6670 updatedelaychange *= 8;
6672 updatedelay += updatedelaychange;
6674 glMatrixMode(GL_MODELVIEW);
6676 glTranslatef(coords.x, coords.y - .02, coords.z);
6677 if (!skeleton.free) {
6678 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6679 glRotatef(yaw, 0, 1, 0);
6683 glColor4f(.4, 1, .4, 1);
6684 glDisable(GL_LIGHTING);
6685 glDisable(GL_TEXTURE_2D);
6688 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6689 XYZ& v0 = skeleton.drawmodel.vertex[i];
6690 glVertex3f(v0.x, v0.y, v0.z);
6697 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6698 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6699 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6700 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6701 glVertex3f(v0.x, v0.y, v0.z);
6702 glVertex3f(v1.x, v1.y, v1.z);
6703 glVertex3f(v1.x, v1.y, v1.z);
6704 glVertex3f(v2.x, v2.y, v2.z);
6705 glVertex3f(v2.x, v2.y, v2.z);
6706 glVertex3f(v0.x, v0.y, v0.z);
6713 terrainlight = terrain.getLighting(coords.x, coords.z);
6714 distance = distsq(&viewer, &coords);
6715 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6720 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6721 if (terrainheight < 1) {
6724 if (terrainheight > 1.7) {
6725 terrainheight = 1.7;
6728 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6729 glDisable(GL_BLEND);
6730 glAlphaFunc(GL_GREATER, 0.0001);
6731 glEnable(GL_TEXTURE_2D);
6733 glDisable(GL_TEXTURE_2D);
6734 glColor4f(.7, .35, 0, .5);
6736 glEnable(GL_LIGHTING);
6739 if (Tutorial::active && id != 0) {
6740 glColor4f(.7, .7, .7, 0.6);
6742 glEnable(GL_LIGHTING);
6744 if (canattack && cananger) {
6745 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6746 glDisable(GL_TEXTURE_2D);
6747 glColor4f(1, 0, 0, 0.8);
6750 glMatrixMode(GL_TEXTURE);
6752 glTranslatef(0, -smoketex, 0);
6753 glTranslatef(-smoketex, 0, 0);
6757 if (Tutorial::active && (id != 0)) {
6758 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6760 skeleton.drawmodel.draw();
6764 if (!playerdetail) {
6765 if (Tutorial::active && (id != 0)) {
6766 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6768 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6772 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6773 if (Tutorial::active && id != 0) {
6775 glMatrixMode(GL_MODELVIEW);
6776 glEnable(GL_TEXTURE_2D);
6777 glColor4f(.7, .7, .7, 0.6);
6779 glEnable(GL_LIGHTING);
6781 if (canattack && cananger) {
6782 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6783 glDisable(GL_TEXTURE_2D);
6784 glColor4f(1, 0, 0, 0.8);
6787 glMatrixMode(GL_TEXTURE);
6789 glTranslatef(0, -smoketex * .6, 0);
6790 glTranslatef(smoketex * .6, 0, 0);
6793 if (Tutorial::active && (id != 0)) {
6794 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6796 skeleton.drawmodel.draw();
6800 if (!playerdetail) {
6801 if (Tutorial::active && (id != 0)) {
6802 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6804 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6810 if (Tutorial::active && id != 0) {
6812 glMatrixMode(GL_MODELVIEW);
6813 glEnable(GL_TEXTURE_2D);
6815 if (skeleton.clothes) {
6819 skeleton.drawmodelclothes.draw();
6822 skeleton.drawmodelclothes.drawimmediate();
6829 if (num_weapons > 0) {
6830 for (k = 0; k < num_weapons; k++) {
6831 int i = weaponids[k];
6832 if (weaponactive == k) {
6833 if (weapons[i].getType() != staff) {
6834 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6835 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6836 weaponattachmuscle = j;
6839 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6840 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) {
6841 weaponrotatemuscle = j;
6844 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6845 if (creature == wolftype) {
6846 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6849 if (weapons[i].getType() == staff) {
6850 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6851 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6852 weaponattachmuscle = j;
6855 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6856 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) {
6857 weaponrotatemuscle = j;
6860 //weaponpoint=jointPos(rightwrist);
6861 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6862 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6863 XYZ tempnormthing, vec1, vec2;
6864 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6865 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6866 CrossProduct(&vec1, &vec2, &tempnormthing);
6867 Normalise(&tempnormthing);
6868 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
6869 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6873 if (weaponactive != k && weaponstuck != k) {
6874 if (weapons[i].getType() == knife) {
6875 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6877 if (weapons[i].getType() == sword) {
6878 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6880 if (weapons[i].getType() == staff) {
6881 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6883 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6884 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) {
6885 weaponrotatemuscle = j;
6889 if (weaponstuck == k) {
6890 if (weaponstuckwhere == 0) {
6891 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6893 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6895 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6896 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) {
6897 weaponrotatemuscle = j;
6901 if (skeleton.free) {
6902 weapons[i].position = weaponpoint * scale + coords;
6903 weapons[i].bigrotation = 0;
6904 weapons[i].bigtilt = 0;
6905 weapons[i].bigtilt2 = 0;
6907 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;
6908 weapons[i].bigrotation = yaw;
6909 weapons[i].bigtilt = tilt;
6910 weapons[i].bigtilt2 = tilt2;
6912 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6913 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6914 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6915 if (weaponactive == k) {
6916 if (weapons[i].getType() == knife) {
6917 weapons[i].smallrotation = 180;
6918 weapons[i].smallrotation2 = 0;
6919 if (isCrouch() || wasCrouch()) {
6920 weapons[i].smallrotation2 = 20;
6922 if (animTarget == hurtidleanim) {
6923 weapons[i].smallrotation2 = 50;
6925 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6926 XYZ temppoint1, temppoint2;
6929 temppoint1 = jointPos(righthand);
6930 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6931 distance = findDistance(&temppoint1, &temppoint2);
6932 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6933 weapons[i].rotation2 *= 360 / 6.28;
6936 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6937 weapons[i].rotation1 *= 360 / 6.28;
6938 weapons[i].rotation3 = 0;
6939 weapons[i].smallrotation = -90;
6940 weapons[i].smallrotation2 = 0;
6941 if (temppoint1.x > temppoint2.x) {
6942 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6945 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6946 XYZ temppoint1, temppoint2;
6949 temppoint1 = jointPos(righthand);
6950 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6951 distance = findDistance(&temppoint1, &temppoint2);
6952 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6953 weapons[i].rotation2 *= 360 / 6.28;
6956 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6957 weapons[i].rotation1 *= 360 / 6.28;
6958 weapons[i].rotation3 = 0;
6959 weapons[i].smallrotation = 90;
6960 weapons[i].smallrotation2 = 0;
6961 if (temppoint1.x > temppoint2.x) {
6962 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6965 if (animTarget == knifethrowanim) {
6966 weapons[i].smallrotation = 90;
6967 //weapons[i].smallrotation2=-90;
6968 weapons[i].smallrotation2 = 0;
6969 weapons[i].rotation1 = 0;
6970 weapons[i].rotation2 = 0;
6971 weapons[i].rotation3 = 0;
6973 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6974 weapons[i].smallrotation = -90;
6975 weapons[i].rotation1 = 0;
6976 weapons[i].rotation2 = 0;
6977 weapons[i].rotation3 = 0;
6980 if (weapons[i].getType() == sword) {
6981 weapons[i].smallrotation = 0;
6982 weapons[i].smallrotation2 = 0;
6983 if (animTarget == knifethrowanim) {
6984 weapons[i].smallrotation = -90;
6985 weapons[i].smallrotation2 = 0;
6986 weapons[i].rotation1 = 0;
6987 weapons[i].rotation2 = 0;
6988 weapons[i].rotation3 = 0;
6990 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)) {
6991 XYZ temppoint1, temppoint2;
6994 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6995 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6996 distance = findDistance(&temppoint1, &temppoint2);
6997 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6998 weapons[i].rotation2 *= 360 / 6.28;
7001 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7002 weapons[i].rotation1 *= 360 / 6.28;
7003 weapons[i].rotation3 = 0;
7004 weapons[i].smallrotation = 90;
7005 weapons[i].smallrotation2 = 0;
7006 if (temppoint1.x > temppoint2.x) {
7007 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7011 if (weapons[i].getType() == staff) {
7012 weapons[i].smallrotation = 100;
7013 weapons[i].smallrotation2 = 0;
7014 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7015 XYZ temppoint1, temppoint2;
7018 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7019 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7020 distance = findDistance(&temppoint1, &temppoint2);
7021 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7022 weapons[i].rotation2 *= 360 / 6.28;
7025 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7026 weapons[i].rotation1 *= 360 / 6.28;
7027 weapons[i].rotation3 = 0;
7028 weapons[i].smallrotation = 90;
7029 weapons[i].smallrotation2 = 0;
7030 if (temppoint1.x > temppoint2.x) {
7031 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7036 if (weaponactive != k && weaponstuck != k) {
7037 if (weapons[i].getType() == knife) {
7038 weapons[i].smallrotation = -70;
7039 weapons[i].smallrotation2 = 10;
7041 if (weapons[i].getType() == sword) {
7042 weapons[i].smallrotation = -100;
7043 weapons[i].smallrotation2 = -8;
7045 if (weapons[i].getType() == staff) {
7046 weapons[i].smallrotation = -100;
7047 weapons[i].smallrotation2 = -8;
7050 if (weaponstuck == k) {
7051 if (weaponstuckwhere == 0) {
7052 weapons[i].smallrotation = 180;
7054 weapons[i].smallrotation = 0;
7056 weapons[i].smallrotation2 = 10;
7063 if (skeleton.free) {
7066 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7069 if (animCurrent != animTarget) {
7072 if (skeleton.free == 2) {
7081 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7083 static float distance;
7084 static float olddistance;
7085 static int intersecting;
7086 static int firstintersecting;
7089 static XYZ start, end;
7090 static float slopethreshold = -.4;
7092 firstintersecting = -1;
7096 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7100 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7102 for (int i = 0; i < 4; i++) {
7103 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7104 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7106 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)));
7107 if (distance < radius) {
7108 point = *p1 - model->Triangles[j].facenormal * distance;
7109 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]])) {
7112 if (!intersecting) {
7113 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7114 &model->vertex[model->Triangles[j].vertex[1]],
7117 if (!intersecting) {
7118 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7119 &model->vertex[model->Triangles[j].vertex[2]],
7122 if (!intersecting) {
7123 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7124 &model->vertex[model->Triangles[j].vertex[2]],
7128 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7132 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)) {
7133 p1->y = point.y + radius;
7134 if ((animTarget == jumpdownanim || isFlip())) {
7135 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7139 if (animTarget == jumpupanim) {
7141 animTarget = getIdle();
7148 pause_sound(whooshsound);
7149 OPENAL_SetVolume(channels[whooshsound], 0);
7152 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7156 animTarget = getLanding();
7157 emit_sound_at(landsound, coords, 128.);
7160 addEnvSound(coords);
7167 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7168 olddistance = distance;
7169 firstintersecting = j;
7174 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7175 if (model->Triangles[j].facenormal.y > slopethreshold) {
7178 start.y -= radius / 4;
7179 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7180 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7181 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7182 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)));
7183 if (distance < radius * .5) {
7184 point = start - model->Triangles[j].facenormal * distance;
7185 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7188 if (!intersecting) {
7189 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7191 if (!intersecting) {
7192 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7194 if (!intersecting) {
7195 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7198 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7199 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7201 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;
7202 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7206 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7209 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7210 olddistance = distance;
7211 firstintersecting = j;
7218 *p = DoRotation(*p, 0, *rotate, 0);
7222 *p1 = DoRotation(*p1, 0, *rotate, 0);
7225 return firstintersecting;
7228 int findPathDist(int start, int end)
7233 unsigned int smallestcount = 1000;
7234 for (char i = 0; i < 50; i++) {
7235 unsigned int count = 0;
7240 while (last != end && count < 30) {
7242 for (int j = 0; j < Game::numpathpoints; j++) {
7243 if (j != last && j != last2 && j != last3 && j != last4) {
7245 if (Game::numpathpointconnect[j]) {
7246 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7247 if (Game::pathpointconnect[j][k] == last) {
7253 if (Game::numpathpointconnect[last]) {
7254 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7255 if (Game::pathpointconnect[last][k] == j) {
7262 if (closest == -1 || Random() % 2 == 0) {
7274 if (count < smallestcount) {
7275 smallestcount = count;
7278 return smallestcount;
7281 void Person::takeWeapon(int weaponId)
7284 weapons[weaponId].owner = id;
7285 if (num_weapons > 0) {
7286 weaponids[num_weapons] = weaponids[0];
7289 weaponids[0] = weaponId;
7292 void Person::addClothes()
7294 if (numclothes > 0) {
7295 for (int i = 0; i < numclothes; i++) {
7302 bool Person::addClothes(const int& clothesId)
7305 const std::string fileName = clothes[clothesId];
7307 GLubyte* array = &skeleton.skinText[0];
7311 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7316 float tintr = clothestintr[clothesId];
7317 float tintg = clothestintg[clothesId];
7318 float tintb = clothestintb[clothesId];
7340 int bytesPerPixel = texture.bpp / 8;
7344 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7345 if (bytesPerPixel == 3) {
7347 } else if ((i + 1) % 4 == 0) {
7348 alphanum = texture.data[i];
7350 if ((i + 1) % 4 || bytesPerPixel == 3) {
7352 texture.data[i] *= tintr;
7355 texture.data[i] *= tintg;
7358 texture.data[i] *= tintb;
7360 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7372 if (aitype != playercontrolled && !Dialog::inDialog()) {
7374 //disable movement in editor
7375 if (Game::editorenabled) {
7380 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7381 Person::players[0]->coords.y > coords.y + 2 &&
7382 !Person::players[0]->onterrain) {
7387 if (aitype == pathfindtype) {
7388 if (finalpathfindpoint == -1) {
7389 float closestdistance;
7390 float tempdist = 0.0f;
7394 closestdistance = -1;
7395 for (int j = 0; j < Game::numpathpoints; j++) {
7396 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7397 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7399 finaltarget = Game::pathpoint[j];
7402 finalpathfindpoint = closest;
7403 for (int j = 0; j < Game::numpathpoints; j++) {
7404 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7405 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7406 if (sq(tempdist) < closestdistance) {
7407 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7408 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7409 closestdistance = sq(tempdist);
7411 finaltarget = colpoint;
7416 finalpathfindpoint = closest;
7418 if (targetpathfindpoint == -1) {
7419 float closestdistance;
7420 float tempdist = 0.0f;
7424 closestdistance = -1;
7425 if (lastpathfindpoint == -1) {
7426 for (int j = 0; j < Game::numpathpoints; j++) {
7427 if (j != lastpathfindpoint) {
7428 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7429 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7434 targetpathfindpoint = closest;
7435 for (int j = 0; j < Game::numpathpoints; j++) {
7436 if (j != lastpathfindpoint) {
7437 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7438 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7439 if (sq(tempdist) < closestdistance) {
7440 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7441 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7442 closestdistance = sq(tempdist);
7449 targetpathfindpoint = closest;
7451 for (int j = 0; j < Game::numpathpoints; j++) {
7452 if (j != lastpathfindpoint &&
7453 j != lastpathfindpoint2 &&
7454 j != lastpathfindpoint3 &&
7455 j != lastpathfindpoint4) {
7457 if (Game::numpathpointconnect[j]) {
7458 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7459 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7465 if (Game::numpathpointconnect[lastpathfindpoint]) {
7466 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7467 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7474 tempdist = findPathDist(j, finalpathfindpoint);
7475 if (closest == -1 || tempdist < closestdistance) {
7476 closestdistance = tempdist;
7482 targetpathfindpoint = closest;
7485 losupdatedelay -= multiplier;
7487 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7488 lookyaw = targetyaw;
7490 //reached target point
7491 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7492 lastpathfindpoint4 = lastpathfindpoint3;
7493 lastpathfindpoint3 = lastpathfindpoint2;
7494 lastpathfindpoint2 = lastpathfindpoint;
7495 lastpathfindpoint = targetpathfindpoint;
7496 if (lastpathfindpoint2 == -1) {
7497 lastpathfindpoint2 = lastpathfindpoint;
7499 if (lastpathfindpoint3 == -1) {
7500 lastpathfindpoint3 = lastpathfindpoint2;
7502 if (lastpathfindpoint4 == -1) {
7503 lastpathfindpoint4 = lastpathfindpoint3;
7505 targetpathfindpoint = -1;
7507 if (distsqflat(&coords, &finalfinaltarget) <
7508 distsqflat(&coords, &finaltarget) ||
7509 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7510 lastpathfindpoint == finalpathfindpoint) {
7511 aitype = passivetype;
7522 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7523 targetyaw += 90 * (whichdirection * 2 - 1);
7526 if (collided < 1 || animTarget != jumpupanim) {
7529 if ((collided > .8 && jumppower >= 5)) {
7533 if ((!Tutorial::active || cananger) &&
7535 !Person::players[0]->dead &&
7536 distsq(&coords, &Person::players[0]->coords) < 400 &&
7538 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7539 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7540 !Game::editorenabled &&
7541 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7542 aitype = attacktypecutoff;
7544 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7545 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7546 !Game::editorenabled) {
7547 aitype = attacktypecutoff;
7550 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7551 losupdatedelay = .2;
7552 for (unsigned j = 0; j < Person::players.size(); j++) {
7553 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7554 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7555 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7556 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7557 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7558 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) ||
7559 (Person::players[j]->animTarget == hanganim &&
7560 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7561 aitype = searchtype;
7563 lastseen = Person::players[j]->coords;
7574 if (aitype == attacktypecutoff && Game::musictype != 2) {
7575 if (creature != wolftype) {
7582 if (aitype != passivetype && Game::leveltime > .5) {
7583 howactive = typeactive;
7586 if (aitype == passivetype) {
7587 aiupdatedelay -= multiplier;
7588 losupdatedelay -= multiplier;
7589 lastseentime += multiplier;
7590 pausetime -= multiplier;
7591 if (lastseentime > 1) {
7595 if (aiupdatedelay < 0) {
7596 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7597 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7598 lookyaw = targetyaw;
7599 aiupdatedelay = .05;
7601 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7602 if (waypointtype[waypoint] == wppause) {
7606 if (waypoint > numwaypoints - 1) {
7612 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7624 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7625 if (!avoidsomething) {
7626 targetyaw += 90 * (whichdirection * 2 - 1);
7628 XYZ leftpos, rightpos;
7629 float leftdist, rightdist;
7630 leftpos = coords + DoRotation(facing, 0, 90, 0);
7631 rightpos = coords - DoRotation(facing, 0, 90, 0);
7632 leftdist = distsq(&leftpos, &avoidwhere);
7633 rightdist = distsq(&rightpos, &avoidwhere);
7634 if (leftdist < rightdist) {
7642 if (collided < 1 || animTarget != jumpupanim) {
7645 if ((collided > .8 && jumppower >= 5)) {
7650 if (!Game::editorenabled) {
7651 if (howactive <= typesleeping) {
7652 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7653 for (int j = 0; j < numenvsounds; j++) {
7654 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7655 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7656 aitype = attacktypecutoff;
7662 if (aitype != passivetype) {
7663 if (howactive == typesleeping) {
7664 setTargetAnimation(getupfromfrontanim);
7666 howactive = typeactive;
7670 if (howactive < typesleeping &&
7671 ((!Tutorial::active || cananger) && hostile) &&
7672 !Person::players[0]->dead &&
7673 distsq(&coords, &Person::players[0]->coords) < 400 &&
7675 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7676 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7677 aitype = attacktypecutoff;
7679 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7680 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7681 aitype = attacktypecutoff;
7685 if (creature == wolftype) {
7687 for (unsigned j = 0; j < Person::players.size(); j++) {
7688 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7689 float smelldistance = 50;
7690 if (j == 0 && Person::players[j]->num_weapons > 0) {
7691 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7692 smelldistance = 100;
7694 if (Person::players[j]->num_weapons == 2) {
7695 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7696 smelldistance = 100;
7701 smelldistance = 100;
7703 windsmell = windvector;
7704 Normalise(&windsmell);
7705 windsmell = windsmell * 2 + Person::players[j]->coords;
7706 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7707 aitype = attacktypecutoff;
7713 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7714 losupdatedelay = .2;
7715 for (unsigned j = 0; j < Person::players.size(); j++) {
7716 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7717 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7718 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7719 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7720 if ((-1 == Object::checkcollide(
7721 DoRotation(jointPos(head), 0, yaw, 0) *
7724 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7725 Person::players[j]->scale +
7726 Person::players[j]->coords) &&
7727 !Person::players[j]->isWallJump()) ||
7728 (Person::players[j]->animTarget == hanganim &&
7729 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7731 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7740 if (lastseentime <= 0) {
7741 aitype = searchtype;
7743 lastseen = Person::players[j]->coords;
7751 if (aitype == attacktypecutoff && Game::musictype != 2) {
7752 if (creature != wolftype) {
7756 if (creature == wolftype) {
7766 if (aitype == searchtype) {
7767 aiupdatedelay -= multiplier;
7768 losupdatedelay -= multiplier;
7770 lastseentime -= multiplier;
7772 lastchecktime -= multiplier;
7774 if (isRun() && !onground) {
7775 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7776 XYZ test2 = coords + facing;
7778 XYZ test = coords + facing;
7780 j = Object::checkcollide(test2, test, laststanding);
7782 j = Object::checkcollide(test2, test);
7786 setTargetAnimation(getStop());
7789 //aitype=passivetype;
7790 aitype = pathfindtype;
7791 finalfinaltarget = waypoints[waypoint];
7792 finalpathfindpoint = -1;
7793 targetpathfindpoint = -1;
7794 lastpathfindpoint = -1;
7795 lastpathfindpoint2 = -1;
7796 lastpathfindpoint3 = -1;
7797 lastpathfindpoint4 = -1;
7803 //check out last seen location
7804 if (aiupdatedelay < 0) {
7805 targetyaw = roughDirectionTo(coords, lastseen);
7806 lookyaw = targetyaw;
7807 aiupdatedelay = .05;
7810 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7813 lastseen.x += (float(Random() % 100) - 50) / 25;
7814 lastseen.z += (float(Random() % 100) - 50) / 25;
7825 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7826 if (!avoidsomething) {
7827 targetyaw += 90 * (whichdirection * 2 - 1);
7829 XYZ leftpos, rightpos;
7830 float leftdist, rightdist;
7831 leftpos = coords + DoRotation(facing, 0, 90, 0);
7832 rightpos = coords - DoRotation(facing, 0, 90, 0);
7833 leftdist = distsq(&leftpos, &avoidwhere);
7834 rightdist = distsq(&rightpos, &avoidwhere);
7835 if (leftdist < rightdist) {
7843 if (collided < 1 || animTarget != jumpupanim) {
7846 if ((collided > .8 && jumppower >= 5)) {
7850 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
7851 for (int k = 0; k < numenvsounds; k++) {
7852 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7853 aitype = attacktypecutoff;
7858 if (!Person::players[0]->dead &&
7859 losupdatedelay < 0 &&
7860 !Game::editorenabled &&
7862 ((!Tutorial::active || cananger) && hostile)) {
7863 losupdatedelay = .2;
7864 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7865 aitype = attacktypecutoff;
7868 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
7869 //TODO: factor out canSeePlayer()
7870 if (distsq(&coords, &Person::players[0]->coords) < 400) {
7871 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
7872 if ((Object::checkcollide(
7873 DoRotation(jointPos(head), 0, yaw, 0) *
7876 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7877 Person::players[0]->scale +
7878 Person::players[0]->coords) == -1) ||
7879 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7880 /* //TODO: changed j to 0 on a whim, make sure this is correct
7881 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7882 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7884 aitype = attacktypecutoff;
7892 if (lastseentime < 0) {
7893 //aitype=passivetype;
7895 aitype = pathfindtype;
7896 finalfinaltarget = waypoints[waypoint];
7897 finalpathfindpoint = -1;
7898 targetpathfindpoint = -1;
7899 lastpathfindpoint = -1;
7900 lastpathfindpoint2 = -1;
7901 lastpathfindpoint3 = -1;
7902 lastpathfindpoint4 = -1;
7906 if (aitype != gethelptype) {
7910 //get help from buddies
7911 if (aitype == gethelptype) {
7912 runninghowlong += multiplier;
7913 aiupdatedelay -= multiplier;
7915 if (aiupdatedelay < 0 || ally == 0) {
7919 //TODO: factor out closest search somehow
7922 float closestdist = -1;
7923 for (unsigned k = 0; k < Person::players.size(); k++) {
7924 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7925 (Person::players[k]->howactive < typedead1) &&
7926 !Person::players[k]->skeleton.free &&
7927 (Person::players[k]->aitype == passivetype)) {
7928 float distance = distsq(&coords, &Person::players[k]->coords);
7929 if (closestdist == -1 || distance < closestdist) {
7930 closestdist = distance;
7935 if (closest != -1) {
7940 lastseen = Person::players[0]->coords;
7946 XYZ facing = coords;
7947 XYZ flatfacing = Person::players[ally]->coords;
7948 facing.y += jointPos(head).y * scale;
7949 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7950 if (-1 != Object::checkcollide(facing, flatfacing)) {
7954 //no available ally, run back to player
7956 Person::players[ally]->skeleton.free ||
7957 Person::players[ally]->aitype != passivetype ||
7958 lastseentime <= 0) {
7959 aitype = searchtype;
7965 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7966 lookyaw = targetyaw;
7967 aiupdatedelay = .05;
7970 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7971 aitype = searchtype;
7973 Person::players[ally]->aitype = searchtype;
7974 if (Person::players[ally]->lastseentime < lastseentime) {
7975 Person::players[ally]->lastseen = lastseen;
7976 Person::players[ally]->lastseentime = lastseentime;
7977 Person::players[ally]->lastchecktime = lastchecktime;
7981 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7982 if (!avoidsomething) {
7983 targetyaw += 90 * (whichdirection * 2 - 1);
7985 XYZ leftpos, rightpos;
7986 float leftdist, rightdist;
7987 leftpos = coords + DoRotation(facing, 0, 90, 0);
7988 rightpos = coords - DoRotation(facing, 0, 90, 0);
7989 leftdist = distsq(&leftpos, &avoidwhere);
7990 rightdist = distsq(&rightpos, &avoidwhere);
7991 if (leftdist < rightdist) {
8006 if (collided < 1 || animTarget != jumpupanim) {
8009 if (collided > .8 && jumppower >= 5) {
8014 //retreiving a weapon on the ground
8015 if (aitype == getweapontype) {
8016 aiupdatedelay -= multiplier;
8017 lastchecktime -= multiplier;
8019 if (aiupdatedelay < 0) {
8025 float closestdist = -1;
8026 for (unsigned k = 0; k < weapons.size(); k++) {
8027 if (weapons[k].owner == -1) {
8028 float distance = distsq(&coords, &weapons[k].position);
8029 if (closestdist == -1 || distance < closestdist) {
8030 closestdist = distance;
8035 if (closest != -1) {
8044 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8045 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8046 aitype = attacktypecutoff;
8050 if (!Person::players[0]->dead) {
8052 if (weapons[ally].owner != -1 ||
8053 distsq(&coords, &weapons[ally].position) > 16) {
8054 aitype = attacktypecutoff;
8057 //TODO: factor these out as moveToward()
8058 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8059 lookyaw = targetyaw;
8060 aiupdatedelay = .05;
8063 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8064 if (!avoidsomething) {
8065 targetyaw += 90 * (whichdirection * 2 - 1);
8067 XYZ leftpos, rightpos;
8068 float leftdist, rightdist;
8069 leftpos = coords + DoRotation(facing, 0, 90, 0);
8070 rightpos = coords - DoRotation(facing, 0, 90, 0);
8071 leftdist = distsq(&leftpos, &avoidwhere);
8072 rightdist = distsq(&rightpos, &avoidwhere);
8073 if (leftdist < rightdist) {
8089 if (animTarget != crouchremoveknifeanim &&
8090 animTarget != removeknifeanim) {
8091 throwtogglekeydown = 0;
8095 if (collided < 1 || animTarget != jumpupanim) {
8098 if ((collided > .8 && jumppower >= 5)) {
8103 if (aitype == attacktypecutoff) {
8104 aiupdatedelay -= multiplier;
8105 //dodge or reverse rabbit kicks, knife throws, flips
8106 if (damage < damagetolerance * 2 / 3) {
8107 if ((Person::players[0]->animTarget == rabbitkickanim ||
8108 Person::players[0]->animTarget == knifethrowanim ||
8109 (Person::players[0]->isFlip() &&
8110 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8111 !Person::players[0]->skeleton.free &&
8112 (aiupdatedelay < .1)) {
8117 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8118 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8119 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8120 if (abs(Random() % 2) == 0) {
8121 setTargetAnimation(backhandspringanim);
8123 setTargetAnimation(rollanim);
8125 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8128 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8129 setTargetAnimation(flipanim);
8134 aiupdatedelay = .02;
8137 //get confused by flips
8138 if (Person::players[0]->isFlip() &&
8139 !Person::players[0]->skeleton.free &&
8140 Person::players[0]->animTarget != walljumprightkickanim &&
8141 Person::players[0]->animTarget != walljumpleftkickanim) {
8142 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8143 if ((1 - damage / damagetolerance) > .5) {
8148 //go for weapon on the ground
8149 if (wentforweapon < 3) {
8150 for (unsigned k = 0; k < weapons.size(); k++) {
8151 if (creature != wolftype) {
8152 if (num_weapons == 0 &&
8153 weapons[k].owner == -1 &&
8154 weapons[k].velocity.x == 0 &&
8155 weapons[k].velocity.z == 0 &&
8156 weapons[k].velocity.y == 0) {
8157 if (distsq(&coords, &weapons[k].position) < 16) {
8160 aitype = getweapontype;
8167 //dodge/reverse walljump kicks
8168 if (damage < damagetolerance / 2) {
8169 if (Animation::animations[animTarget].height != highheight) {
8170 if (damage < damagetolerance * .5 &&
8171 ((Person::players[0]->animTarget == walljumprightkickanim ||
8172 Person::players[0]->animTarget == walljumpleftkickanim) &&
8173 ((aiupdatedelay < .15 &&
8175 (aiupdatedelay < .08 &&
8176 difficulty != 2)))) {
8181 //walked off a ledge (?)
8182 if (isRun() && !onground) {
8183 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8184 XYZ test2 = coords + facing;
8186 XYZ test = coords + facing;
8188 j = Object::checkcollide(test2, test, laststanding);
8190 j = Object::checkcollide(test2, test);
8194 setTargetAnimation(getStop());
8197 aitype = pathfindtype;
8198 finalfinaltarget = waypoints[waypoint];
8199 finalpathfindpoint = -1;
8200 targetpathfindpoint = -1;
8201 lastpathfindpoint = -1;
8202 lastpathfindpoint2 = -1;
8203 lastpathfindpoint3 = -1;
8204 lastpathfindpoint4 = -1;
8210 //lose sight of player in the air (?)
8211 if (Person::players[0]->coords.y > coords.y + 5 &&
8212 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8213 !Person::players[0]->onterrain) {
8214 aitype = pathfindtype;
8215 finalfinaltarget = waypoints[waypoint];
8216 finalpathfindpoint = -1;
8217 targetpathfindpoint = -1;
8218 lastpathfindpoint = -1;
8219 lastpathfindpoint2 = -1;
8220 lastpathfindpoint3 = -1;
8221 lastpathfindpoint4 = -1;
8223 //it's time to think (?)
8224 if (aiupdatedelay < 0 &&
8225 !Animation::animations[animTarget].attack &&
8226 animTarget != staggerbackhighanim &&
8227 animTarget != staggerbackhardanim &&
8228 animTarget != backhandspringanim &&
8229 animTarget != dodgebackanim) {
8231 if (weaponactive == -1 && num_weapons > 0) {
8232 drawkeydown = Random() % 2;
8236 rabbitkickenabled = Random() % 2;
8238 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8239 XYZ targetpoint = Person::players[0]->coords;
8240 float vellength = findLength(&velocity);
8241 if (vellength != 0 &&
8242 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8243 targetpoint += Person::players[0]->velocity *
8244 findDistance(&Person::players[0]->coords, &coords) / vellength;
8246 targetyaw = roughDirectionTo(coords, targetpoint);
8247 lookyaw = targetyaw;
8248 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8250 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8252 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8253 distsq(&coords, &Person::players[0]->coords) < 9) &&
8254 Person::players[0]->weaponactive != -1) {
8256 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8261 //chill out around the corpse
8262 if (Person::players[0]->dead) {
8264 if (Random() % 10 == 0) {
8267 if (Random() % 100 == 0) {
8268 aitype = pathfindtype;
8269 finalfinaltarget = waypoints[waypoint];
8270 finalpathfindpoint = -1;
8271 targetpathfindpoint = -1;
8272 lastpathfindpoint = -1;
8273 lastpathfindpoint2 = -1;
8274 lastpathfindpoint3 = -1;
8275 lastpathfindpoint4 = -1;
8284 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8285 targetyaw += 90 * (whichdirection * 2 - 1);
8288 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8293 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8298 if (aitype != playercontrolled &&
8303 for (unsigned j = 0; j < Person::players.size(); j++) {
8304 if (j != id && !Person::players[j]->skeleton.free &&
8305 Person::players[j]->hasvictim &&
8306 (Tutorial::active && reversaltrain ||
8307 Random() % 2 == 0 && difficulty == 2 ||
8308 Random() % 4 == 0 && difficulty == 1 ||
8309 Random() % 8 == 0 && difficulty == 0 ||
8310 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8311 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8312 (Random() % 2 == 0 || difficulty == 2) ||
8313 (isIdle() || isRun()) &&
8314 Person::players[j]->weaponactive != -1 ||
8315 Person::players[j]->animTarget == swordslashanim &&
8316 weaponactive != -1 ||
8317 Person::players[j]->animTarget == staffhitanim ||
8318 Person::players[j]->animTarget == staffspinhitanim)) {
8319 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8320 Person::players[j]->victim == Person::players[id] &&
8321 (Person::players[j]->animTarget == sweepanim ||
8322 Person::players[j]->animTarget == spinkickanim ||
8323 Person::players[j]->animTarget == staffhitanim ||
8324 Person::players[j]->animTarget == staffspinhitanim ||
8325 Person::players[j]->animTarget == winduppunchanim ||
8326 Person::players[j]->animTarget == upunchanim ||
8327 Person::players[j]->animTarget == wolfslapanim ||
8328 Person::players[j]->animTarget == knifeslashstartanim ||
8329 Person::players[j]->animTarget == swordslashanim &&
8330 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8331 weaponactive != -1))) {
8341 Person::players[target]->Reverse();
8348 if (collided > .8 && jumppower >= 5 ||
8349 distsq(&coords, &Person::players[0]->coords) > 400 &&
8351 creature == rabbittype) {
8354 //TODO: why are we controlling the human?
8355 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8356 Person::players[0]->jumpkeydown = 0;
8358 if (Person::players[0]->animTarget == jumpdownanim &&
8359 distsq(&Person::players[0]->coords, &coords) < 40) {
8366 if (Tutorial::active) {
8372 XYZ facing = coords;
8373 XYZ flatfacing = Person::players[0]->coords;
8374 facing.y += jointPos(head).y * scale;
8375 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8376 if (occluded >= 2) {
8377 if (-1 != Object::checkcollide(facing, flatfacing)) {
8381 if (lastseentime <= 0 &&
8382 (creature != wolftype ||
8383 weaponstuck == -1)) {
8384 aitype = searchtype;
8386 lastseen = Person::players[0]->coords;
8395 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8396 (aitype == attacktypecutoff ||
8397 aitype == searchtype)) {
8398 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8399 XYZ test = Person::players[0]->coords;
8401 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8407 if (aitype == passivetype && !(numwaypoints > 1) ||
8409 pause && damage > superpermanentdamage) {
8428 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8429 facing = flatfacing;
8431 if (aitype == attacktypecutoff) {
8432 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8433 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8434 } else if (howactive >= typesleeping) {
8435 targetheadyaw = targetyaw;
8436 targetheadpitch = 0;
8438 if (interestdelay <= 0) {
8439 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8440 headtarget = coords;
8441 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8442 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8443 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8444 headtarget += facing * 1.5;
8446 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8447 targetheadpitch = pitchTo(coords, headtarget);