2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decalstoggle;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern float smoketex;
59 extern bool reversaltrain;
60 extern bool canattack;
62 extern float damagedealt;
64 extern float hostiletime;
66 extern bool gamestarted;
68 extern XYZ envsound[30];
69 extern float envsoundvol[30];
70 extern int numenvsounds;
71 extern float envsoundlife[30];
73 extern XYZ windvector;
75 std::vector<std::shared_ptr<Person>> Person::players;
80 , animCurrent(bounceidleanim)
81 , animTarget(bounceidleanim)
88 , howactive(typeactive)
90 , superruntoggle(false)
124 , rabbitkickenabled(false)
137 , superpermanentdamage(0)
172 , isplayerfriend(false)
176 , normalsupdatedelay(0)
180 , forwardkeydown(false)
181 , forwardstogglekeydown(false)
182 , rightkeydown(false)
186 , jumptogglekeydown(false)
187 , crouchkeydown(false)
188 , crouchtogglekeydown(false)
190 , drawtogglekeydown(false)
191 , throwkeydown(false)
192 , throwtogglekeydown(false)
193 , attackkeydown(false)
215 , whichdirection(false)
216 , whichdirectiondelay(0)
217 , avoidsomething(false)
227 , lefthandmorphness(0)
228 , righthandmorphness(0)
232 , targetlefthandmorphness(0)
233 , targetrighthandmorphness(0)
234 , targetheadmorphness(1)
235 , targetchestmorphness(0)
236 , targettailmorphness(0)
237 , lefthandmorphstart(0)
238 , lefthandmorphend(0)
239 , righthandmorphstart(0)
240 , righthandmorphend(0)
250 , highreversaldelay(0)
251 , lowreversaldelay(0)
300 , weaponstuckwhere(0)
313 , finalpathfindpoint(0)
314 , targetpathfindpoint(0)
315 , lastpathfindpoint(0)
316 , lastpathfindpoint2(0)
317 , lastpathfindpoint3(0)
318 , lastpathfindpoint4(0)
338 , neckspurtparticledelay(0)
342 , rabbitkickragdoll(false)
344 , tempanimation("Tempanim", lowheight, neutral)
348 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
349 setProportions(1, 1, 1, 1);
352 /* Read a person in tfile. Throws an error if it’s not valid */
353 Person::Person(FILE* tfile, int mapvers, unsigned i)
357 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
359 funpackf(tfile, "Bi", &howactive);
361 howactive = typeactive;
364 funpackf(tfile, "Bf", &scale);
369 funpackf(tfile, "Bb", &immobile);
374 funpackf(tfile, "Bf", &yaw);
379 if (num_weapons < 0 || num_weapons > 5) {
380 throw InvalidPersonException();
382 if (num_weapons > 0 && num_weapons < 5) {
383 for (int j = 0; j < num_weapons; j++) {
384 weaponids[j] = weapons.size();
386 funpackf(tfile, "Bi", &type);
387 weapons.push_back(Weapon(type, id));
390 funpackf(tfile, "Bi", &numwaypoints);
391 for (int j = 0; j < numwaypoints; j++) {
392 funpackf(tfile, "Bf", &waypoints[j].x);
393 funpackf(tfile, "Bf", &waypoints[j].y);
394 funpackf(tfile, "Bf", &waypoints[j].z);
396 funpackf(tfile, "Bi", &waypointtype[j]);
398 waypointtype[j] = wpkeepwalking;
402 funpackf(tfile, "Bi", &waypoint);
403 if (waypoint > (numwaypoints - 1)) {
407 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
408 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
409 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
410 funpackf(tfile, "Bf Bf", &power, &speedmult);
413 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
415 setProportions(1, 1, 1, 1);
418 funpackf(tfile, "Bi", &numclothes);
419 for (int k = 0; k < numclothes; k++) {
421 funpackf(tfile, "Bi", &templength);
422 for (int l = 0; l < templength; l++) {
423 funpackf(tfile, "Bb", &clothes[k][l]);
425 clothes[k][templength] = '\0';
426 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
431 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
434 scale = PersonType::types[creature].defaultScale;
438 realoldcoords = coords;
441 void Person::changeCreatureType(person_type type)
446 scale = PersonType::types[creature].defaultScale;
447 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
450 void Person::skeletonLoad()
454 PersonType::types[creature].figureFileName,
455 PersonType::types[creature].lowFigureFileName,
456 PersonType::types[creature].clothesFileName,
457 PersonType::types[creature].modelFileNames[0],
458 PersonType::types[creature].modelFileNames[1],
459 PersonType::types[creature].modelFileNames[2],
460 PersonType::types[creature].modelFileNames[3],
461 PersonType::types[creature].modelFileNames[4],
462 PersonType::types[creature].modelFileNames[5],
463 PersonType::types[creature].modelFileNames[6],
464 PersonType::types[creature].lowModelFileName,
465 PersonType::types[creature].modelClothesFileName,
466 PersonType::types[creature].clothes);
468 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
471 void Person::setProportions(float head, float body, float arms, float legs)
473 proportions[0] = head;
474 proportions[1] = body;
475 proportions[2] = arms;
476 proportions[3] = legs;
479 float Person::getProportion(int part) const
481 return proportions[part];
484 XYZ Person::getProportionXYZ(int part) const
486 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
496 * GameTick/doPlayerCollisions
498 void Person::CheckKick()
500 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
504 if (Animation::animations[victim->animTarget].height != lowheight) {
505 float damagemult = PersonType::types[creature].power * power * power;
506 XYZ relative = velocity;
508 Normalise(&relative);
512 if (!Tutorial::active) {
513 emit_sound_at(heavyimpactsound, victim->coords);
516 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
517 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
520 victim->DoDamage(100 * damagemult / victim->protectionhigh);
527 animTarget = backflipanim;
529 velocity = facing * -10;
533 resume_stream(whooshsound);
536 award_bonus(id, cannon);
537 } else if (victim->isCrouch()) {
538 animTarget = rabbitkickreversedanim;
539 animCurrent = rabbitkickreversedanim;
540 victim->animCurrent = rabbitkickreversalanim;
541 victim->animTarget = rabbitkickreversalanim;
547 victim->oldcoords = victim->coords;
548 coords = victim->coords;
549 victim->targetyaw = targetyaw;
550 victim->victim = this->shared_from_this();
557 * GameTick::doPlayerCollisions - spread fire between players
558 * GameTick::ProcessDevKeys - press f to ignite
559 * Person::DoStuff - spread fire from lit campfires and bushes
561 void Person::CatchFire()
563 XYZ flatfacing, flatvelocity;
565 for (int i = 0; i < 10; i++) {
566 howmany = fabs(Random() % (skeleton.joints.size()));
568 flatvelocity = skeleton.joints[howmany].velocity;
569 flatfacing = skeleton.joints[howmany].position * scale + coords;
571 flatvelocity = velocity;
572 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
574 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
579 emit_sound_at(firestartsound, coords);
581 emit_stream_at(stream_firesound, coords);
589 * idle animation for this creature (depending on status)
591 int Person::getIdle()
593 if (Dialog::inDialog() && (howactive == typeactive) && PersonType::types[creature].hasAnimTalkIdle()) {
594 return PersonType::types[creature].animTalkIdle;
596 if (hasvictim && (victim != this->shared_from_this())) {
597 if ((!victim->dead && victim->aitype != passivetype &&
598 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
599 victim->id < Person::players.size())) {
600 if ((isPlayerControlled() && (stunned <= 0) && !hasWeapon()) || pause) {
601 return PersonType::types[creature].animFightIdle;
603 if (isPlayerControlled() && (stunned <= 0) && hasWeapon()) {
604 if (weapons[weaponids[weaponactive]].getType() == knife) {
605 return knifefightidleanim;
607 if (weapons[weaponids[weaponactive]].getType() == sword && victim->hasWeapon()) {
608 return swordfightidlebothanim;
610 if (weapons[weaponids[weaponactive]].getType() == sword) {
611 return swordfightidleanim;
613 if (weapons[weaponids[weaponactive]].getType() == staff) {
614 return swordfightidleanim;
617 if (!isPlayerControlled() && (stunned <= 0) && creature != wolftype) {
618 return fightsidestep;
622 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && PersonType::types[creature].hasAnimHurtIdle()) {
623 return PersonType::types[creature].animHurtIdle;
625 if (howactive == typesitting) {
628 if (howactive == typesittingwall) {
631 if (howactive == typesleeping) {
634 if (howactive == typedead1) {
637 if (howactive == typedead2) {
640 if (howactive == typedead3) {
643 if (howactive == typedead4) {
646 return PersonType::types[creature].animBounceIdle;
650 * crouch animation for this creature
652 int Person::getCrouch()
654 return PersonType::types[creature].animCrouch;
658 * running animation for this creature (can be upright or all fours)
662 if (superruntoggle && (!hasWeapon())) {
663 return PersonType::types[creature].animRunning;
665 return PersonType::types[creature].animRun;
671 int Person::getStop()
673 return PersonType::types[creature].animStop;
678 int Person::getLanding()
680 return PersonType::types[creature].animLanding;
685 int Person::getLandhard()
687 return PersonType::types[creature].animLandingHard;
693 * Person::DoAnimations
696 SolidHitBonus(int playerid)
698 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
699 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
701 award_bonus(playerid, solidhit);
706 * spawns blood effects
708 void Person::DoBlood(float howmuch, int which)
710 // FIXME: should abstract out inputs
711 static int bleedxint, bleedyint;
713 if (bloodtoggle && !Tutorial::active) {
714 if (bleeding <= 0 && spurt) {
716 for (int i = 0; i < 3; i++) {
717 // emit blood particles
720 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
721 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
722 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
723 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
726 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
727 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
728 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
729 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
732 if (Random() % 2 == 0) { // 50% chance
733 for (int i = 0; i < 3; i++) {
734 if (Random() % 2 != 0) {
735 // emit teeth particles
738 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
739 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
742 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
743 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
747 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
749 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
751 Sprite::setLastSpriteSpecial(3); // sets it to teeth
757 // FIXME: manipulating attributes
758 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
761 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) {
762 bleedxint = abs(Random() % 512);
763 bleedyint = abs(Random() % 512);
767 bleedy /= realtexdetail;
768 bleedx /= realtexdetail;
769 direction = abs(Random() % 2) * 2 - 1;
778 * spawns big blood effects and ???
779 * modifies character's skin texture
781 void Person::DoBloodBig(float howmuch, int which)
783 static int bleedxint, bleedyint, i, j;
785 if (howmuch && id == 0) {
789 if (!Tutorial::active || id == 0) {
790 if (!isPlayerControlled() && howmuch > 0) {
794 if (creature == wolftype) {
795 int i = abs(Random() % 2);
797 whichsound = snarlsound;
800 whichsound = snarl2sound;
803 if (creature == rabbittype) {
804 int i = abs(Random() % 2);
806 whichsound = rabbitpainsound;
808 if (i == 1 && howmuch >= 2) {
809 whichsound = rabbitpain1sound;
813 if (whichsound != -1) {
814 emit_sound_at(whichsound, coords);
820 if (id == 0 && howmuch > 0) {
824 if (bloodtoggle && decalstoggle && !Tutorial::active) {
825 if (bleeding <= 0 && spurt) {
827 for (int i = 0; i < 3; i++) {
828 // emit blood particles
829 // FIXME: copypaste from above
832 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
833 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
834 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
835 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
838 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
839 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
840 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
841 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
846 // weird texture manipulation code follows.
847 // looks like this is painting blood onto the character's skin texture
848 // FIXME: surely there's a better way
850 int offsetx = 0, offsety = 0;
852 offsety = Random() % 40;
853 offsetx = abs(Random() % 60);
855 if (which == 190 || which == 185) {
856 offsety = Random() % 40;
857 offsetx = abs(Random() % 100) - 20;
860 offsety = Random() % 10;
861 offsetx = Random() % 10;
864 offsety = Random() % 20;
865 offsetx = Random() % 20;
867 if (which == 220 || which == 215) {
876 for (i = 0; i < 512; i++) {
877 for (j = 0; j < 512; j++) {
878 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) {
906 if (endx > 512 - 1) {
909 if (endy > 512 - 1) {
919 startx /= realtexdetail;
920 starty /= realtexdetail;
921 endx /= realtexdetail;
922 endy /= realtexdetail;
924 int texdetailint = realtexdetail;
926 for (i = startx; i < endx; i++) {
927 for (j = starty; j < endy; j++) {
928 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) {
929 color = Random() % 85 + 170;
930 where = i * skeleton.skinsize * 3 + j * 3;
931 if (skeleton.skinText[where + 0] > color / 2) {
932 skeleton.skinText[where + 0] = color / 2;
934 skeleton.skinText[where + 1] = 0;
935 skeleton.skinText[where + 2] = 0;
939 skeleton.drawmodel.textureptr.bind();
944 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) {
945 bleedxint = abs(Random() % 512);
946 bleedyint = abs(Random() % 512);
948 bleedy = bleedxint + offsetx;
949 bleedx = bleedyint + offsety;
950 bleedy /= realtexdetail;
951 bleedx /= realtexdetail;
958 if (bleedx > skeleton.skinsize - 1) {
959 bleedx = skeleton.skinsize - 1;
961 if (bleedy > skeleton.skinsize - 1) {
962 bleedy = skeleton.skinsize - 1;
964 direction = abs(Random() % 2) * 2 - 1;
966 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
967 deathbleeding += bleeding;
968 bloodloss += bleeding * 3;
970 if (!Tutorial::active && !isPlayerControlled() && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
971 if (abs(Random() % 2) == 0) {
972 aitype = gethelptype;
975 aitype = attacktypecutoff;
985 * similar to DoBloodBig
987 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
991 static XYZ startpoint, endpoint, colpoint, movepoint;
992 static float rotationpoint;
994 static XYZ p1, p2, p3, p0;
997 float coordsx, coordsy;
1000 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1002 if (!skeleton.free) {
1003 where = DoRotation(where, 0, -yaw, 0);
1007 startpoint.y += 100;
1012 // ray testing for a tri in the character model
1013 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1014 if (whichtri != -1) {
1015 // low level geometry math
1017 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1018 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1019 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1021 bary.x = distsq(&p0, &p1);
1022 bary.y = distsq(&p0, &p2);
1023 bary.z = distsq(&p0, &p3);
1025 total = bary.x + bary.y + bary.z;
1030 bary.x = 1 - bary.x;
1031 bary.y = 1 - bary.y;
1032 bary.z = 1 - bary.z;
1034 total = bary.x + bary.y + bary.z;
1039 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1040 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1041 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1042 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1043 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1044 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1045 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;
1046 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;
1048 if (bleeding <= 0 && spurt) {
1050 for (int i = 0; i < 3; i++) {
1051 // emit blood particles
1052 // FIXME: more copypaste code
1054 if (skeleton.free) {
1055 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1056 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1057 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1058 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1061 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1062 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1063 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1064 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1069 // texture manipulation follows
1071 int offsetx = 0, offsety = 0;
1072 offsetx = (1 + coordsy) * 512 - 291;
1073 offsety = coordsx * 512 - 437;
1080 for (i = 0; i < 512; i++) {
1081 for (j = 0; j < 512; j++) {
1082 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) {
1109 if (endx > 512 - 1) {
1112 if (endy > 512 - 1) {
1115 if (endx < startx) {
1118 if (endy < starty) {
1122 startx /= realtexdetail;
1123 starty /= realtexdetail;
1124 endx /= realtexdetail;
1125 endy /= realtexdetail;
1127 int texdetailint = realtexdetail;
1129 for (i = startx; i < endx; i++) {
1130 for (j = starty; j < endy; j++) {
1131 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) {
1132 color = Random() % 85 + 170;
1133 where = i * skeleton.skinsize * 3 + j * 3;
1134 if (skeleton.skinText[where + 0] > color / 2) {
1135 skeleton.skinText[where + 0] = color / 2;
1137 skeleton.skinText[where + 1] = 0;
1138 skeleton.skinText[where + 2] = 0;
1139 } 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) {
1140 color = Random() % 85 + 170;
1141 where = i * skeleton.skinsize * 3 + j * 3;
1142 if (skeleton.skinText[where + 0] > color / 2) {
1143 skeleton.skinText[where + 0] = color / 2;
1145 skeleton.skinText[where + 1] = 0;
1146 skeleton.skinText[where + 2] = 0;
1150 skeleton.drawmodel.textureptr.bind();
1153 bleedy = (1 + coordsy) * 512;
1154 bleedx = coordsx * 512;
1155 bleedy /= realtexdetail;
1156 bleedx /= realtexdetail;
1163 if (bleedx > skeleton.skinsize - 1) {
1164 bleedx = skeleton.skinsize - 1;
1166 if (bleedy > skeleton.skinsize - 1) {
1167 bleedy = skeleton.skinsize - 1;
1169 direction = abs(Random() % 2) * 2 - 1;
1171 if (whichtri == -1) {
1175 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1176 deathbleeding += bleeding;
1177 bloodloss += bleeding * 3;
1179 if (!Tutorial::active && !isPlayerControlled() && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1180 if (abs(Random() % 2) == 0) {
1181 aitype = gethelptype;
1184 aitype = attacktypecutoff;
1195 * guessing this performs a reversal
1197 void Person::Reverse()
1199 if (!((victim->isPlayerControlled() || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1203 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1207 if (animTarget == sweepanim) {
1208 animTarget = sweepreversedanim;
1209 animCurrent = sweepreversedanim;
1210 victim->animCurrent = sweepreversalanim;
1211 victim->animTarget = sweepreversalanim;
1213 if (animTarget == spinkickanim) {
1214 animTarget = spinkickreversedanim;
1215 animCurrent = spinkickreversedanim;
1216 victim->animCurrent = spinkickreversalanim;
1217 victim->animTarget = spinkickreversalanim;
1219 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1220 if (animTarget == rabbittacklinganim) {
1223 victim->frameCurrent = 6;
1224 victim->frameTarget = 7;
1226 animTarget = upunchreversedanim;
1227 animCurrent = upunchreversedanim;
1228 victim->animCurrent = upunchreversalanim;
1229 victim->animTarget = upunchreversalanim;
1231 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1232 if (victim->hasWeapon()) {
1233 victim->throwtogglekeydown = 1;
1234 XYZ tempVelocity = victim->velocity * .2;
1235 if (tempVelocity.x == 0) {
1236 tempVelocity.x = .1;
1238 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1239 victim->num_weapons--;
1240 if (victim->num_weapons) {
1241 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1242 if (victim->weaponstuck == victim->num_weapons) {
1243 victim->weaponstuck = 0;
1247 victim->weaponactive = -1;
1248 for (unsigned j = 0; j < Person::players.size(); j++) {
1249 Person::players[j]->wentforweapon = 0;
1253 animTarget = staffhitreversedanim;
1254 animCurrent = staffhitreversedanim;
1255 victim->animCurrent = staffhitreversalanim;
1256 victim->animTarget = staffhitreversalanim;
1258 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1259 if (victim->hasWeapon()) {
1260 victim->throwtogglekeydown = 1;
1261 XYZ tempVelocity = victim->velocity * .2;
1262 if (tempVelocity.x == 0) {
1263 tempVelocity.x = .1;
1265 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1266 victim->num_weapons--;
1267 if (victim->num_weapons) {
1268 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1269 if (victim->weaponstuck == victim->num_weapons) {
1270 victim->weaponstuck = 0;
1274 victim->weaponactive = -1;
1275 for (unsigned j = 0; j < Person::players.size(); j++) {
1276 Person::players[j]->wentforweapon = 0;
1279 animTarget = staffspinhitreversedanim;
1280 animCurrent = staffspinhitreversedanim;
1281 victim->animCurrent = staffspinhitreversalanim;
1282 victim->animTarget = staffspinhitreversalanim;
1284 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1285 if (victim->hasWeapon()) {
1286 victim->throwtogglekeydown = 1;
1287 XYZ tempVelocity = victim->velocity * .2;
1288 if (tempVelocity.x == 0) {
1289 tempVelocity.x = .1;
1291 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1292 victim->num_weapons--;
1293 if (victim->num_weapons) {
1294 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1295 if (victim->weaponstuck == victim->num_weapons) {
1296 victim->weaponstuck = 0;
1300 victim->weaponactive = -1;
1301 for (unsigned j = 0; j < Person::players.size(); j++) {
1302 Person::players[j]->wentforweapon = 0;
1305 animTarget = swordslashreversedanim;
1306 animCurrent = swordslashreversedanim;
1307 victim->animCurrent = swordslashreversalanim;
1308 victim->animTarget = swordslashreversalanim;
1310 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1311 if (victim->hasWeapon()) {
1312 victim->throwtogglekeydown = 1;
1313 XYZ tempVelocity = victim->velocity * .2;
1314 if (tempVelocity.x == 0) {
1315 tempVelocity.x = .1;
1317 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1318 victim->num_weapons--;
1319 if (victim->num_weapons) {
1320 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1321 if (victim->weaponstuck == victim->num_weapons) {
1322 victim->weaponstuck = 0;
1326 victim->weaponactive = -1;
1327 for (unsigned j = 0; j < Person::players.size(); j++) {
1328 Person::players[j]->wentforweapon = 0;
1331 animTarget = knifeslashreversedanim;
1332 animCurrent = knifeslashreversedanim;
1333 victim->animCurrent = knifeslashreversalanim;
1334 victim->animTarget = knifeslashreversalanim;
1336 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1337 victim->targettilt2 = targettilt2;
1338 victim->frameCurrent = frameCurrent;
1339 victim->frameTarget = frameTarget;
1340 victim->target = target;
1341 victim->velocity = 0;
1342 victim->oldcoords = victim->coords;
1343 victim->coords = coords;
1344 victim->targetyaw = targetyaw;
1345 victim->yaw = targetyaw;
1346 victim->victim = this->shared_from_this();
1348 if (animTarget == winduppunchanim) {
1349 animTarget = winduppunchblockedanim;
1350 victim->animTarget = blockhighleftanim;
1351 victim->frameTarget = 1;
1352 victim->target = .5;
1353 victim->victim = this->shared_from_this();
1354 victim->targetyaw = targetyaw + 180;
1356 if (animTarget == wolfslapanim) {
1357 animTarget = winduppunchblockedanim;
1358 victim->animTarget = blockhighleftanim;
1359 victim->frameTarget = 1;
1360 victim->target = .5;
1361 victim->victim = this->shared_from_this();
1362 victim->targetyaw = targetyaw + 180;
1364 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->hasWeapon()) {
1365 animTarget = swordslashparriedanim;
1366 parriedrecently = .4;
1367 victim->parriedrecently = 0;
1368 victim->animTarget = swordslashparryanim;
1369 victim->frameTarget = 1;
1370 victim->target = .5;
1371 victim->victim = this->shared_from_this();
1372 victim->targetyaw = targetyaw + 180;
1374 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1375 if (victim->hasWeapon()) {
1376 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1377 if (weapons[victim->weaponids[0]].getType() == staff) {
1378 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1380 if (weapons[weaponids[0]].getType() == staff) {
1381 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1383 emit_sound_at(swordstaffsound, victim->coords);
1385 emit_sound_at(metalhitsound, victim->coords);
1389 victim->Puff(righthand);
1391 victim->frameTarget = 0;
1392 victim->animTarget = staggerbackhighanim;
1393 victim->targetyaw = targetyaw + 180;
1395 aim = DoRotation(facing, 0, 90, 0) * 21;
1397 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1398 victim->num_weapons--;
1399 if (victim->num_weapons) {
1400 victim->weaponids[0] = victim->weaponids[num_weapons];
1401 if (victim->weaponstuck == victim->num_weapons) {
1402 victim->weaponstuck = 0;
1405 victim->weaponactive = -1;
1406 for (unsigned i = 0; i < Person::players.size(); i++) {
1407 Person::players[i]->wentforweapon = 0;
1411 if (abs(Random() % 20) == 0) {
1413 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1414 if (weapons[victim->weaponids[0]].getType() == staff) {
1415 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1417 if (weapons[weaponids[0]].getType() == staff) {
1418 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1421 emit_sound_at(swordstaffsound, coords);
1423 emit_sound_at(metalhitsound, coords);
1431 animTarget = staggerbackhighanim;
1432 targetyaw = targetyaw + 180;
1434 aim = DoRotation(facing, 0, 90, 0) * 21;
1436 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1439 weaponids[0] = weaponids[num_weapons];
1440 if (weaponstuck == num_weapons) {
1445 for (unsigned i = 0; i < Person::players.size(); i++) {
1446 Person::players[i]->wentforweapon = 0;
1451 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1452 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1453 victim->animTarget = dodgebackanim;
1454 victim->frameTarget = 0;
1458 rotatetarget = coords - victim->coords;
1459 Normalise(&rotatetarget);
1460 victim->targetyaw = -asin(0 - rotatetarget.x);
1461 victim->targetyaw *= 360 / 6.28;
1462 if (rotatetarget.z < 0) {
1463 victim->targetyaw = 180 - victim->targetyaw;
1466 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1468 victim->lastattack3 = victim->lastattack2;
1469 victim->lastattack2 = victim->lastattack;
1470 victim->lastattack = victim->animTarget;
1472 victim->animTarget = sweepanim;
1473 victim->frameTarget = 0;
1477 rotatetarget = coords - victim->coords;
1478 Normalise(&rotatetarget);
1479 victim->targetyaw = -asin(0 - rotatetarget.x);
1480 victim->targetyaw *= 360 / 6.28;
1481 if (rotatetarget.z < 0) {
1482 victim->targetyaw = 180 - victim->targetyaw;
1485 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1487 victim->lastattack3 = victim->lastattack2;
1488 victim->lastattack2 = victim->lastattack;
1489 victim->lastattack = victim->animTarget;
1495 victim->velocity = 0;
1497 if (!isPlayerControlled()) {
1499 if (escapednum < 2) {
1500 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1501 if ((Random() % chances) == 0) {
1507 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1515 void Person::DoDamage(float howmuch)
1519 damagetaken += howmuch / power;
1521 damagedealt += howmuch / power;
1525 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1530 if (!Tutorial::active) {
1531 damage += howmuch / power;
1532 permanentdamage += howmuch / 2 / power;
1533 superpermanentdamage += howmuch / 4 / power;
1536 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1539 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1544 camerashake += howmuch / 100;
1545 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1546 blackout = damage / damagetolerance;
1554 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1555 aitype = attacktypecutoff;
1557 if (!Tutorial::active && !isPlayerControlled() && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1558 if (abs(Random() % 2) == 0) {
1559 aitype = gethelptype;
1562 aitype = attacktypecutoff;
1567 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1570 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1571 if (skeleton.free) {
1572 flatvelocity2 = skeleton.joints[i].velocity;
1573 flatfacing2 = skeleton.joints[i].position * scale + coords;
1575 flatvelocity2 = velocity;
1576 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1578 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1579 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1580 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1581 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1582 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1583 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1586 emit_sound_at(splattersound, coords);
1591 if (!dead && creature == wolftype) {
1592 award_bonus(0, Wolfbonus);
1599 if (!Tutorial::active || id == 0) {
1600 if (speechdelay <= 0 && !dead && !isPlayerControlled()) {
1601 int whichsound = -1;
1603 if (creature == wolftype) {
1604 int i = abs(Random() % 2);
1606 whichsound = snarlsound;
1609 whichsound = snarl2sound;
1612 if (creature == rabbittype) {
1613 int i = abs(Random() % 2);
1615 whichsound = rabbitpainsound;
1617 if (i == 1 && damage > damagetolerance) {
1618 whichsound = rabbitpain1sound;
1622 if (whichsound != -1) {
1623 emit_sound_at(whichsound, coords);
1624 addEnvSound(coords);
1632 * calculate/animate head facing direction?
1634 void Person::DoHead()
1636 static XYZ rotatearound;
1638 static float lookspeed = 500;
1640 if (!freeze && !winfreeze) {
1643 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1644 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1646 while (targetheadyaw > 180) {
1647 targetheadyaw -= 360;
1649 while (targetheadyaw < -180) {
1650 targetheadyaw += 360;
1653 if (targetheadyaw > 160) {
1654 targetheadpitch = targetheadpitch * -1;
1656 if (targetheadyaw < -160) {
1657 targetheadpitch = targetheadpitch * -1;
1659 if (targetheadyaw > 160) {
1660 targetheadyaw = targetheadyaw - 180;
1662 if (targetheadyaw < -160) {
1663 targetheadyaw = targetheadyaw + 180;
1666 if (targetheadpitch > 120) {
1667 targetheadpitch = 120;
1669 if (targetheadpitch < -120) {
1670 targetheadpitch = -120;
1672 if (targetheadyaw > 120) {
1673 targetheadyaw = 120;
1675 if (targetheadyaw < -120) {
1676 targetheadyaw = -120;
1680 targetheadpitch = 0;
1683 if (targetheadyaw > 80) {
1686 if (targetheadyaw < -80) {
1687 targetheadyaw = -80;
1689 if (targetheadpitch > 50) {
1690 targetheadpitch = 50;
1692 if (targetheadpitch < -50) {
1693 targetheadpitch = -50;
1697 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1698 headyaw = targetheadyaw;
1699 } else if (headyaw > targetheadyaw) {
1700 headyaw -= multiplier * lookspeed;
1701 } else if (headyaw < targetheadyaw) {
1702 headyaw += multiplier * lookspeed;
1705 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1706 headpitch = targetheadpitch;
1707 } else if (headpitch > targetheadpitch) {
1708 headpitch -= multiplier * lookspeed / 2;
1709 } else if (headpitch < targetheadpitch) {
1710 headpitch += multiplier * lookspeed / 2;
1713 rotatearound = jointPos(neck);
1714 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1718 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1719 facing = DoRotation(facing, headpitch * .4, 0, 0);
1720 facing = DoRotation(facing, 0, headyaw * .4, 0);
1723 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1724 facing = DoRotation(facing, headpitch * .8, 0, 0);
1725 facing = DoRotation(facing, 0, headyaw * .8, 0);
1728 if (animTarget == walkanim) {
1729 facing = DoRotation(facing, headpitch * .6, 0, 0);
1730 facing = DoRotation(facing, 0, headyaw * .6, 0);
1733 skeleton.specialforward[0] = facing;
1734 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1735 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1736 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1737 skeleton.FindRotationMuscle(i, animTarget);
1744 * ragdolls character?
1746 void Person::RagDoll(bool checkcollision)
1751 if (!skeleton.free) {
1755 if (id == 0 && isFlip()) {
1763 facing = DoRotation(facing, 0, yaw, 0);
1765 skeleton.freetime = 0;
1767 skeleton.longdead = 0;
1770 skeleton.broken = 0;
1771 skeleton.spinny = 1;
1773 skeleton.freefall = 1;
1775 if (!isnormal(velocity.x)) {
1778 if (!isnormal(velocity.y)) {
1781 if (!isnormal(velocity.z)) {
1784 if (!isnormal(yaw)) {
1787 if (!isnormal(coords.x)) {
1790 if (!isnormal(tilt)) {
1793 if (!isnormal(tilt2)) {
1797 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1798 skeleton.joints[i].delay = 0;
1799 skeleton.joints[i].locked = 0;
1800 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1801 if (!isnormal(skeleton.joints[i].position.x)) {
1802 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1804 if (!isnormal(skeleton.joints[i].position.x)) {
1805 skeleton.joints[i].position = coords;
1807 skeleton.joints[i].position.y += .1;
1808 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1809 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1812 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1813 skeleton.joints[i].velocity = 0;
1814 skeleton.joints[i].velchange = 0;
1816 skeleton.DoConstraints(&coords, &scale);
1817 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1818 skeleton.DoConstraints(&coords, &scale);
1819 skeleton.DoConstraints(&coords, &scale);
1820 skeleton.DoConstraints(&coords, &scale);
1821 skeleton.DoConstraints(&coords, &scale);
1824 speed = targetFrame().speed * 2;
1825 if (currentFrame().speed > targetFrame().speed) {
1826 speed = currentFrame().speed * 2;
1829 speed = transspeed * 2;
1834 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1835 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
1836 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);
1838 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1840 change.x = (float)(Random() % 100) / 100;
1841 change.y = (float)(Random() % 100) / 100;
1842 change.z = (float)(Random() % 100) / 100;
1843 skeleton.joints[i].velocity += change;
1844 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1846 change.x = (float)(Random() % 100) / 100;
1847 change.y = (float)(Random() % 100) / 100;
1848 change.z = (float)(Random() % 100) / 100;
1849 skeleton.joints[i].velchange += change;
1850 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1853 if (checkcollision) {
1856 if (!skeleton.joints.empty()) {
1859 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1860 average += skeleton.joints[j].position;
1862 average /= skeleton.joints.size();
1863 coords += average * scale;
1864 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1865 skeleton.joints[j].position -= average;
1869 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1870 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1871 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1872 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1875 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1876 coords.x = lowpoint.x;
1877 coords.z = lowpoint.z;
1886 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1887 velocity += skeleton.joints[i].velocity * scale;
1889 velocity /= skeleton.joints.size();
1892 if (Random() % 2 == 0) {
1893 if (hasWeapon() && animTarget != rabbitkickanim && num_weapons > 0) {
1894 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1895 weapons[weaponids[0]].velocity.x += .01;
1898 weaponids[0] = weaponids[num_weapons];
1899 if (weaponstuck == num_weapons) {
1904 for (unsigned i = 0; i < Person::players.size(); i++) {
1905 Person::players[i]->wentforweapon = 0;
1910 animTarget = bounceidleanim;
1911 animCurrent = bounceidleanim;
1919 void Person::FootLand(bodypart whichfoot, float opacity)
1921 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1922 cerr << "FootLand called on wrong bodypart" << endl;
1925 static XYZ terrainlight;
1926 static XYZ footvel, footpoint;
1927 if (opacity >= 1 || skiddelay <= 0) {
1930 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1931 if (distsq(&footpoint, &viewer)) {
1932 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1934 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1935 footvel = velocity / 5;
1936 if (footvel.y < .8) {
1939 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1940 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1941 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1942 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1943 if (environment == snowyenvironment) {
1944 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1946 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1948 } else if (environment == grassyenvironment) {
1949 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1950 } else if (environment == desertenvironment) {
1951 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1953 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1957 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1958 footvel = velocity / 5;
1959 if (footvel.y < .8) {
1962 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1963 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1964 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1971 * make a puff effect at a body part (dust effect?)
1973 void Person::Puff(int whichlabel)
1975 static XYZ footvel, footpoint;
1978 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1979 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1983 * I think I added this in an attempt to clean up code
1985 void Person::setTargetAnimation(int animation)
1987 animTarget = animation;
1996 void Person::DoAnimations()
1998 if (!skeleton.free) {
1999 static float oldtarget;
2001 if (isIdle() && animCurrent != getIdle()) {
2002 normalsupdatedelay = 0;
2005 if (animTarget == tempanim || animCurrent == tempanim) {
2006 Animation::animations[tempanim] = tempanimation;
2008 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2015 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2016 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2018 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2021 if (!crouchkeydown && velocity.y >= -15) {
2025 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2030 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2032 if (normaldotproduct(targfacing, velocity) >= -.3) {
2033 animTarget = flipanim;
2035 animTarget = backflipanim;
2037 crouchtogglekeydown = 1;
2046 if (Animation::animations[animTarget].attack != reversed) {
2049 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2050 crouchtogglekeydown = 0;
2051 if (isPlayerControlled()) {
2055 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && isPlayerControlled() && (escapednum < 2 || reversaltrain)) {
2059 crouchtogglekeydown = 1;
2063 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2065 normalsupdatedelay = 0;
2070 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2072 emit_sound_at(fireendsound, coords);
2073 pause_sound(stream_firesound);
2077 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2078 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2081 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2082 if (normaldotproduct(victim->facing, facing) > 0) {
2083 victim->animTarget = rabbittackledbackanim;
2085 victim->animTarget = rabbittackledfrontanim;
2087 victim->frameTarget = 2;
2090 victim->targetyaw = yaw;
2091 if (victim->aitype == gethelptype) {
2092 victim->DoDamage(victim->damagetolerance - victim->damage);
2094 if (PersonType::types[creature].hasClaws) {
2096 emit_sound_at(clawslicesound, victim->coords);
2098 victim->DoBloodBig(1 / victim->armorhead, 210);
2100 award_bonus(id, TackleBonus,
2101 victim->aitype == gethelptype ? 50 : 0);
2105 if (!drawtogglekeydown && drawkeydown && (!hasWeapon() || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2106 if (weapons[weaponids[0]].getType() == knife) {
2109 emit_sound_at(knifedrawsound, coords, 128);
2110 } else if (weaponactive == 0) {
2112 emit_sound_at(knifesheathesound, coords);
2115 drawtogglekeydown = 1;
2118 if (!Tutorial::active || id == 0) {
2119 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2120 int whichsound = -1;
2122 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2123 if (targetFrame().label == 1) {
2124 whichsound = footstepsound;
2126 whichsound = footstepsound2;
2128 if (targetFrame().label == 1) {
2129 FootLand(leftfoot, 1);
2131 if (targetFrame().label == 2) {
2132 FootLand(rightfoot, 1);
2134 if (targetFrame().label == 3 && isRun()) {
2135 FootLand(rightfoot, 1);
2136 FootLand(leftfoot, 1);
2139 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2140 if (targetFrame().label == 1) {
2141 whichsound = footstepsound3;
2143 whichsound = footstepsound4;
2148 if (targetFrame().label == 1) {
2149 whichsound = footstepsound3;
2151 whichsound = footstepsound4;
2154 if (targetFrame().label == 4 && (!hasWeapon() || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2155 if (Animation::animations[animTarget].attack != neutral) {
2156 unsigned r = abs(Random() % 3);
2158 whichsound = lowwhooshsound;
2161 whichsound = midwhooshsound;
2164 whichsound = highwhooshsound;
2167 if (Animation::animations[animTarget].attack == neutral) {
2168 whichsound = movewhooshsound;
2170 } else if (targetFrame().label == 4) {
2171 whichsound = knifeswishsound;
2173 if (targetFrame().label == 8 && !Tutorial::active) {
2174 whichsound = landsound2;
2177 if (whichsound != -1) {
2178 emit_sound_at(whichsound, coords, 256.);
2181 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2182 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2183 addEnvSound(coords, 15);
2185 addEnvSound(coords, 6);
2190 if (targetFrame().label == 3) {
2192 emit_sound_at(whichsound, coords, 128.);
2199 if (!Tutorial::active || id == 0) {
2200 if (speechdelay <= 0) {
2201 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2202 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2203 int whichsound = -1;
2204 if (targetFrame().label == 4 && !isPlayerControlled()) {
2205 if (Animation::animations[animTarget].attack != neutral) {
2206 unsigned r = abs(Random() % 4);
2207 whichsound = PersonType::types[creature].soundsAttack[r];
2212 if (whichsound != -1) {
2213 emit_sound_at(whichsound, coords);
2220 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2221 FootLand(leftfoot, 1);
2222 FootLand(rightfoot, 1);
2226 currentoffset = targetoffset;
2227 frameTarget = frameCurrent;
2228 animCurrent = animTarget;
2231 if (animCurrent == removeknifeanim && currentFrame().label == 5) {
2232 for (unsigned i = 0; i < weapons.size(); i++) {
2233 if (weapons[i].owner == -1) {
2234 if (distsqflat(&coords, &weapons[i].position) < 4 && !hasWeapon()) {
2235 if (distsq(&coords, &weapons[i].position) >= 1) {
2236 if (weapons[i].getType() != staff) {
2237 emit_sound_at(knifedrawsound, coords, 128.);
2247 if (animCurrent == crouchremoveknifeanim && currentFrame().label == 5) {
2248 for (unsigned i = 0; i < weapons.size(); i++) {
2249 bool willwork = true;
2250 if (weapons[i].owner != -1) {
2251 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2252 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2253 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2259 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2260 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && !hasWeapon()) {
2261 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2262 bool fleshstuck = false;
2263 if (weapons[i].owner != -1) {
2264 if (victim->weaponstuck != -1) {
2265 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2271 emit_sound_at(fleshstabremovesound, coords, 128.);
2273 if (weapons[i].getType() != staff) {
2274 emit_sound_at(knifedrawsound, coords, 128.);
2277 if (weapons[i].owner != -1) {
2278 victim = Person::players[weapons[i].owner];
2279 if (victim->num_weapons == 1) {
2280 victim->num_weapons = 0;
2282 victim->num_weapons = 1;
2285 //victim->weaponactive=-1;
2286 victim->skeleton.longdead = 0;
2287 victim->skeleton.free = 1;
2288 victim->skeleton.broken = 0;
2290 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2291 victim->skeleton.joints[j].velchange = 0;
2292 victim->skeleton.joints[j].locked = 0;
2298 Normalise(&relative);
2299 XYZ footvel, footpoint;
2301 footpoint = weapons[i].position;
2302 if (victim->weaponstuck != -1) {
2303 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2305 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2307 weapons[i].bloody = 2;
2308 weapons[i].blooddrip = 5;
2309 victim->weaponstuck = -1;
2312 if (victim->num_weapons > 0) {
2313 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2314 victim->weaponstuck = 0;
2316 if (victim->weaponids[0] == int(i)) {
2317 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2321 victim->jointVel(abdomen) += relative * 6;
2322 victim->jointVel(neck) += relative * 6;
2323 victim->jointVel(rightshoulder) += relative * 6;
2324 victim->jointVel(leftshoulder) += relative * 6;
2333 if (animCurrent == drawleftanim && currentFrame().label == 5) {
2336 emit_sound_at(knifedrawsound, coords, 128.);
2337 } else if (weaponactive == 0) {
2339 if (num_weapons == 2) {
2341 buffer = weaponids[0];
2342 weaponids[0] = weaponids[1];
2343 weaponids[1] = buffer;
2345 emit_sound_at(knifesheathesound, coords, 128.);
2349 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2350 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2351 Normalise(&rotatetarget);
2352 targetyaw = -asin(0 - rotatetarget.x);
2353 targetyaw *= 360 / 6.28;
2354 if (rotatetarget.z < 0) {
2355 targetyaw = 180 - targetyaw;
2358 if (animTarget == walljumprightkickanim) {
2361 if (animTarget == walljumpleftkickanim) {
2368 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2372 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2380 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2381 animTarget = rabbittackleanim;
2383 emit_sound_at(jumpsound, coords);
2391 targetloc = velocity;
2392 Normalise(&targetloc);
2393 targetloc += coords;
2394 for (unsigned i = 0; i < Person::players.size(); i++) {
2396 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2397 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2402 if (closestid != -1) {
2403 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2405 victim = Person::players[closestid];
2406 coords = victim->coords;
2407 animCurrent = rabbittacklinganim;
2408 animTarget = rabbittacklinganim;
2412 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2413 rotatetarget = coords - victim->coords;
2414 Normalise(&rotatetarget);
2415 targetyaw = -asin(0 - rotatetarget.x);
2416 targetyaw *= 360 / 6.28;
2417 if (rotatetarget.z < 0) {
2418 targetyaw = 180 - targetyaw;
2421 if (animTarget != rabbitrunninganim) {
2422 emit_sound_at(jumpsound, coords, 128.);
2429 float damagemult = PersonType::types[creature].power * power;
2431 damagemult /= victim->damagetolerance / 200;
2433 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)) {
2434 if (animCurrent == spinkickanim && currentFrame().label == 5) {
2435 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2440 if (Random() % 2 || PersonType::types[creature].hasClaws) {
2443 if (PersonType::types[creature].hasClaws) {
2447 if (!Tutorial::active) {
2448 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2450 if (PersonType::types[creature].hasClaws) {
2451 emit_sound_at(clawslicesound, victim->coords, 128.);
2453 victim->DoBloodBig(2 / victim->armorhead, 175);
2457 relative = victim->coords - coords;
2459 Normalise(&relative);
2460 relative = DoRotation(relative, 0, -90, 0);
2461 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2462 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2464 victim->jointVel(head) += relative * damagemult * 200;
2466 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2472 if (animCurrent == wolfslapanim && currentFrame().label == 5) {
2473 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2478 if (Random() % 2 || PersonType::types[creature].hasClaws) {
2480 if (PersonType::types[creature].hasClaws) {
2484 emit_sound_at(whooshhitsound, victim->coords);
2485 if (PersonType::types[creature].hasClaws) {
2486 emit_sound_at(clawslicesound, victim->coords, 128.);
2488 victim->DoBloodBig(2, 175);
2492 relative = victim->coords - coords;
2494 Normalise(&relative);
2496 Normalise(&relative);
2497 relative = DoRotation(relative, 0, 90, 0);
2498 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2499 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2501 victim->jointVel(head) += relative * damagemult * 100;
2503 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2507 if (animCurrent == walljumprightkickanim && currentFrame().label == 5) {
2508 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2515 if (!Tutorial::active) {
2516 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2518 if (PersonType::types[creature].hasClaws) {
2519 emit_sound_at(clawslicesound, victim->coords, 128.);
2521 victim->DoBloodBig(2 / victim->armorhead, 175);
2527 Normalise(&relative);
2528 relative = DoRotation(relative, 0, -90, 0);
2529 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2530 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2532 victim->jointVel(head) += relative * damagemult * 200;
2534 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2536 if (victim->damage > victim->damagetolerance) {
2537 award_bonus(id, style);
2544 if (animCurrent == walljumpleftkickanim && currentFrame().label == 5) {
2545 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2552 if (!Tutorial::active) {
2553 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2555 if (PersonType::types[creature].hasClaws) {
2556 emit_sound_at(clawslicesound, victim->coords, 128.);
2558 victim->DoBloodBig(2 / victim->armorhead, 175);
2564 Normalise(&relative);
2565 relative = DoRotation(relative, 0, 90, 0);
2566 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2567 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2569 victim->jointVel(head) += relative * damagemult * 200;
2571 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2573 if (victim->damage > victim->damagetolerance) {
2574 award_bonus(id, style);
2581 if (animCurrent == blockhighleftstrikeanim && currentFrame().label == 5) {
2582 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2591 emit_sound_at(whooshhitsound, victim->coords);
2594 relative = victim->coords - coords;
2596 Normalise(&relative);
2597 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2598 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2600 victim->jointVel(head) += relative * damagemult * 100;
2602 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2606 if (animCurrent == killanim && currentFrame().label == 8) {
2607 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2612 emit_sound_at(whooshhitsound, victim->coords, 128.);
2614 victim->skeleton.longdead = 0;
2615 victim->skeleton.free = 1;
2616 victim->skeleton.broken = 0;
2617 victim->skeleton.spinny = 1;
2619 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2620 victim->skeleton.joints[i].velchange = 0;
2621 victim->skeleton.joints[i].delay = 0;
2622 victim->skeleton.joints[i].locked = 0;
2623 //victim->skeleton.joints[i].velocity=0;
2629 Normalise(&relative);
2630 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2631 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2632 victim->skeleton.joints[i].position.y += relative.y * .3;
2633 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2634 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2636 victim->Puff(abdomen);
2637 victim->jointVel(abdomen).y = relative.y * 400;
2641 if (animCurrent == killanim && currentFrame().label == 5) {
2642 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2647 if (!Tutorial::active) {
2648 emit_sound_at(heavyimpactsound, coords, 128.);
2651 relative = victim->coords - coords;
2653 Normalise(&relative);
2654 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2655 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2657 victim->Puff(abdomen);
2658 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2662 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2663 victim->jointVel(abdomen) += relative * damagemult * 300;
2667 if (animCurrent == dropkickanim && currentFrame().label == 7) {
2668 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2673 if (!Tutorial::active) {
2674 emit_sound_at(thudsound, coords);
2677 victim->skeleton.longdead = 0;
2678 victim->skeleton.free = 1;
2679 victim->skeleton.broken = 0;
2680 victim->skeleton.spinny = 1;
2682 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2683 victim->skeleton.joints[i].velchange = 0;
2684 //victim->skeleton.joints[i].delay=0;
2685 victim->skeleton.joints[i].locked = 0;
2688 relative = victim->coords - coords;
2689 Normalise(&relative);
2691 Normalise(&relative);
2692 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2693 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2695 if (!victim->dead) {
2699 victim->Puff(abdomen);
2700 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2701 victim->jointVel(abdomen) += relative * damagemult * 200;
2703 if (!victim->dead) {
2709 if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 5) {
2712 if (!victim->skeleton.free) {
2718 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2719 emit_sound_at(knifesheathesound, coords, 128.);
2722 if (victim && hasvictim) {
2723 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2725 XYZ where, startpoint, endpoint, movepoint, colpoint;
2726 float rotationpoint;
2728 if (weapons[weaponids[weaponactive]].getType() == knife) {
2729 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2730 where -= victim->coords;
2731 if (!victim->skeleton.free) {
2732 where = DoRotation(where, 0, -victim->yaw, 0);
2736 startpoint.y += 100;
2740 if (weapons[weaponids[weaponactive]].getType() == sword) {
2741 where = weapons[weaponids[weaponactive]].position;
2742 where -= victim->coords;
2743 if (!victim->skeleton.free) {
2744 where = DoRotation(where, 0, -victim->yaw, 0);
2747 where = weapons[weaponids[weaponactive]].tippoint;
2748 where -= victim->coords;
2749 if (!victim->skeleton.free) {
2750 where = DoRotation(where, 0, -victim->yaw, 0);
2754 if (weapons[weaponids[weaponactive]].getType() == staff) {
2755 where = weapons[weaponids[weaponactive]].position;
2756 where -= victim->coords;
2757 if (!victim->skeleton.free) {
2758 where = DoRotation(where, 0, -victim->yaw, 0);
2761 where = weapons[weaponids[weaponactive]].tippoint;
2762 where -= victim->coords;
2763 if (!victim->skeleton.free) {
2764 where = DoRotation(where, 0, -victim->yaw, 0);
2770 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2772 if (whichtri != -1) {
2773 if (victim->dead != 2) {
2774 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2775 if (!victim->dead) {
2776 award_bonus(id, FinishedBonus);
2780 weapons[weaponids[weaponactive]].bloody = 2;
2783 victim->skeleton.longdead = 0;
2784 victim->skeleton.free = 1;
2785 victim->skeleton.broken = 0;
2787 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2788 victim->skeleton.joints[i].velchange = 0;
2789 victim->skeleton.joints[i].locked = 0;
2790 //victim->skeleton.joints[i].velocity=0;
2792 emit_sound_at(fleshstabsound, coords, 128);
2794 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2795 weapons[weaponids[weaponactive]].blooddrip += 5;
2796 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2798 if (whichtri == -1) {
2800 emit_sound_at(knifesheathesound, coords, 128.);
2806 if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 6) {
2808 emit_sound_at(knifedrawsound, coords, 128);
2811 if (victim && hasvictim) {
2812 XYZ footvel, footpoint;
2814 emit_sound_at(fleshstabremovesound, coords, 128.);
2817 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2819 if (weapons[weaponids[weaponactive]].getType() == sword) {
2820 XYZ where, startpoint, endpoint, movepoint;
2821 float rotationpoint;
2824 where = weapons[weaponids[weaponactive]].position;
2825 where -= victim->coords;
2826 if (!victim->skeleton.free) {
2827 where = DoRotation(where, 0, -victim->yaw, 0);
2830 where = weapons[weaponids[weaponactive]].tippoint;
2831 where -= victim->coords;
2832 if (!victim->skeleton.free) {
2833 where = DoRotation(where, 0, -victim->yaw, 0);
2839 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2840 footpoint += victim->coords;
2842 if (whichtri == -1) {
2843 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2846 if (weapons[weaponids[weaponactive]].getType() == staff) {
2847 XYZ where, startpoint, endpoint, movepoint;
2848 float rotationpoint;
2851 where = weapons[weaponids[weaponactive]].position;
2852 where -= victim->coords;
2853 if (!victim->skeleton.free) {
2854 where = DoRotation(where, 0, -victim->yaw, 0);
2857 where = weapons[weaponids[weaponactive]].tippoint;
2858 where -= victim->coords;
2859 if (!victim->skeleton.free) {
2860 where = DoRotation(where, 0, -victim->yaw, 0);
2866 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2867 footpoint += victim->coords;
2869 if (whichtri == -1) {
2870 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2873 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2875 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2876 victim->skeleton.longdead = 0;
2877 victim->skeleton.free = 1;
2878 victim->skeleton.broken = 0;
2880 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2881 victim->skeleton.joints[i].velchange = 0;
2882 victim->skeleton.joints[i].locked = 0;
2883 //victim->skeleton.joints[i].velocity=0;
2889 Normalise(&relative);
2890 //victim->Puff(abdomen);
2892 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2895 if (victim->bloodloss < victim->damagetolerance) {
2896 victim->bloodloss += 1000;
2900 victim->jointVel(abdomen) += relative * damagemult * 20;
2904 if (!hasvictim && onterrain) {
2905 weapons[weaponids[weaponactive]].bloody = 0;
2906 weapons[weaponids[weaponactive]].blooddrip = 0;
2910 if (animCurrent == upunchanim && currentFrame().label == 5) {
2911 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2920 if (!Tutorial::active) {
2921 emit_sound_at(heavyimpactsound, victim->coords, 128);
2926 relative = victim->coords - coords;
2928 Normalise(&relative);
2929 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2930 victim->skeleton.joints[i].velocity = relative * 30;
2932 victim->jointVel(head) += relative * damagemult * 150;
2934 victim->frameTarget = 0;
2935 victim->animTarget = staggerbackhardanim;
2936 victim->targetyaw = targetyaw + 180;
2938 victim->stunned = 1;
2941 victim->Puff(abdomen);
2942 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2948 if (animCurrent == winduppunchanim && currentFrame().label == 5) {
2949 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2954 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2955 if (!Tutorial::active) {
2956 emit_sound_at(thudsound, victim->coords);
2958 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2959 if (!Tutorial::active) {
2960 emit_sound_at(whooshhitsound, victim->coords);
2963 if (!Tutorial::active) {
2964 emit_sound_at(heavyimpactsound, victim->coords);
2968 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
2972 relative = victim->coords - coords;
2974 Normalise(&relative);
2976 Normalise(&relative);
2977 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2978 victim->skeleton.joints[i].velocity = relative * 5;
2980 victim->jointVel(abdomen) += relative * damagemult * 400;
2982 victim->frameTarget = 0;
2983 victim->animTarget = staggerbackhardanim;
2984 victim->targetyaw = targetyaw + 180;
2986 victim->stunned = 1;
2988 victim->Puff(abdomen);
2989 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2995 if (animCurrent == blockhighleftanim && currentFrame().label == 5) {
2996 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2997 if (victim->id == 0) {
3000 emit_sound_at(landsound2, victim->coords);
3006 if (animCurrent == swordslashparryanim && currentFrame().label == 5) {
3007 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3008 if (victim->id == 0) {
3013 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3014 if (weapons[victim->weaponids[0]].getType() == staff) {
3015 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3017 if (weapons[weaponids[0]].getType() == staff) {
3018 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3021 emit_sound_at(swordstaffsound, victim->coords);
3023 emit_sound_at(metalhitsound, victim->coords);
3031 if (animCurrent == knifethrowanim && currentFrame().label == 5) {
3035 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);
3037 weapons[weaponids[0]].thrown(aim * 50);
3040 weaponids[0] = weaponids[num_weapons];
3046 if (animCurrent == knifeslashstartanim && currentFrame().label == 5) {
3048 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3050 if (!Tutorial::active) {
3051 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3054 award_bonus(id, Slicebonus);
3055 if (!Tutorial::active) {
3056 emit_sound_at(knifeslicesound, victim->coords);
3058 //victim->jointVel(abdomen)+=relative*damagemult*200;
3059 if (Animation::animations[victim->animTarget].attack && (!victim->isPlayerControlled() || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3060 if (victim->id != 0 || difficulty == 2) {
3061 victim->frameTarget = 0;
3062 victim->animTarget = staggerbackhardanim;
3063 victim->targetyaw = targetyaw + 180;
3067 victim->lowreversaldelay = 0;
3068 victim->highreversaldelay = 0;
3069 if (!isPlayerControlled()) {
3070 weaponmissdelay = .6;
3073 if (!Tutorial::active) {
3074 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3075 weapons[weaponids[weaponactive]].bloody = 1;
3077 weapons[weaponids[weaponactive]].blooddrip += 3;
3080 XYZ footvel, footpoint;
3082 if (skeleton.free) {
3083 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3085 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3087 if (Tutorial::active) {
3088 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3091 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3093 footvel = DoRotation(facing, 0, 90, 0) * .8;
3094 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3095 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3096 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3097 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3099 victim->DoDamage(damagemult * 0);
3103 if (animCurrent == swordslashanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3104 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3105 if (!victim->hasWeapon() || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3106 award_bonus(id, Slashbonus);
3108 if (!Tutorial::active) {
3109 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3110 victim->DoBloodBig(2 / victim->armorhigh, 190);
3112 victim->DoBloodBig(2 / victim->armorhigh, 185);
3114 victim->deathbleeding = 1;
3115 emit_sound_at(swordslicesound, victim->coords);
3116 victim->frameTarget = 0;
3117 victim->animTarget = staggerbackhardanim;
3118 victim->targetyaw = targetyaw + 180;
3120 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3121 weapons[weaponids[weaponactive]].bloody = 1;
3123 weapons[weaponids[weaponactive]].blooddrip += 3;
3125 float bloodlossamount;
3126 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3127 victim->bloodloss += bloodlossamount / victim->armorhigh;
3128 victim->DoDamage(damagemult * 0);
3130 XYZ footvel, footpoint;
3132 if (skeleton.free) {
3133 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3135 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3138 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3140 footvel = DoRotation(facing, 0, 90, 0) * .8;
3142 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3143 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3144 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3145 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3148 if (victim->hasWeapon()) {
3149 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3150 if (weapons[victim->weaponids[0]].getType() == staff) {
3151 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3153 if (weapons[weaponids[0]].getType() == staff) {
3154 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3157 emit_sound_at(swordstaffsound, victim->coords);
3159 emit_sound_at(metalhitsound, victim->coords);
3164 victim->Puff(righthand);
3166 victim->frameTarget = 0;
3167 victim->animTarget = staggerbackhighanim;
3168 victim->targetyaw = targetyaw + 180;
3170 aim = DoRotation(facing, 0, 90, 0) * 21;
3172 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3173 victim->num_weapons--;
3174 if (victim->num_weapons) {
3175 victim->weaponids[0] = victim->weaponids[num_weapons];
3176 if (victim->weaponstuck == victim->num_weapons) {
3177 victim->weaponstuck = 0;
3180 victim->weaponactive = -1;
3181 for (unsigned i = 0; i < Person::players.size(); i++) {
3182 Person::players[i]->wentforweapon = 0;
3188 if (animCurrent == staffhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3189 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3190 if (!Tutorial::active) {
3191 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3196 if (Random() % 2 || PersonType::types[creature].hasClaws) {
3199 emit_sound_at(staffheadsound, victim->coords);
3203 relative = victim->coords - coords;
3205 Normalise(&relative);
3206 relative = DoRotation(relative, 0, 90, 0);
3208 Normalise(&relative);
3209 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3210 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3212 victim->jointVel(head) += relative * damagemult * 230;
3213 victim->jointVel(neck) += relative * damagemult * 230;
3215 if (!Tutorial::active) {
3216 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3218 award_bonus(id, solidhit, 30);
3223 if (animCurrent == staffspinhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3224 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3225 if (!Tutorial::active) {
3226 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3231 if (Random() % 2 || PersonType::types[creature].hasClaws) {
3234 emit_sound_at(staffheadsound, victim->coords);
3238 relative = victim->coords - coords;
3240 Normalise(&relative);
3241 relative = DoRotation(relative, 0, -90, 0);
3242 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3243 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3245 victim->jointVel(head) += relative * damagemult * 220;
3246 victim->jointVel(neck) += relative * damagemult * 220;
3248 if (!Tutorial::active) {
3249 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3251 award_bonus(id, solidhit, 60);
3256 if (animCurrent == staffgroundsmashanim && currentFrame().label == 5) {
3257 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3259 if (!Tutorial::active) {
3260 if (!victim->dead) {
3261 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3266 if (Random() % 2 || PersonType::types[creature].hasClaws) {
3269 emit_sound_at(staffbodysound, victim->coords);
3271 victim->skeleton.longdead = 0;
3272 victim->skeleton.free = 1;
3273 victim->skeleton.broken = 0;
3275 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3276 victim->skeleton.joints[i].velchange = 0;
3277 victim->skeleton.joints[i].locked = 0;
3278 //victim->skeleton.joints[i].velocity=0;
3285 Normalise(&relative);
3286 if (!victim->dead) {
3287 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3288 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3290 victim->jointVel(abdomen) += relative * damagemult * 40;
3293 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3294 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3297 victim->Puff(abdomen);
3298 if (!Tutorial::active) {
3299 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3301 if (!victim->dead) {
3302 award_bonus(id, solidhit, 40);
3308 if (animCurrent == lowkickanim && currentFrame().label == 5) {
3309 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3315 relative = victim->coords - coords;
3317 Normalise(&relative);
3321 if (Animation::animations[victim->animTarget].height == lowheight) {
3327 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3328 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3330 victim->jointVel(head) += relative * damagemult * 200;
3331 if (!Tutorial::active) {
3332 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3335 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3336 if (victim->howactive == typesleeping) {
3337 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3339 if (PersonType::types[creature].hasClaws) {
3340 emit_sound_at(clawslicesound, victim->coords, 128.);
3342 victim->DoBloodBig(2 / victim->armorhead, 175);
3345 if (victim->damage >= victim->damagetolerance) {
3348 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3349 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3351 victim->jointVel(abdomen) += relative * damagemult * 200;
3352 victim->frameTarget = 0;
3353 victim->animTarget = staggerbackhighanim;
3354 victim->targetyaw = targetyaw + 180;
3356 if (!Tutorial::active) {
3357 emit_sound_at(landsound2, victim->coords, 128.);
3359 victim->Puff(abdomen);
3360 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3361 if (PersonType::types[creature].hasClaws) {
3362 emit_sound_at(clawslicesound, victim->coords, 128.);
3364 victim->DoBloodBig(2 / victim->armorhigh, 170);
3370 if (animCurrent == sweepanim && currentFrame().label == 5) {
3371 if ((victim->animTarget != jumpupanim) &&
3372 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3373 (victim != this->shared_from_this())) {
3378 if (!Tutorial::active) {
3379 emit_sound_at(landsound2, victim->coords, 128.);
3382 relative = victim->coords - coords;
3384 Normalise(&relative);
3386 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3389 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3390 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3392 relative = DoRotation(relative, 0, -90, 0);
3394 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3395 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) {
3396 victim->skeleton.joints[i].velocity = relative * 80;
3399 victim->Puff(rightankle);
3400 victim->Puff(leftankle);
3401 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3403 if (victim->damage >= victim->damagetolerance) {
3406 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3407 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3409 relative = DoRotation(relative, 0, -90, 0);
3410 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3411 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) {
3412 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3415 victim->jointVel(abdomen) += relative * damagemult * 200;
3416 victim->frameTarget = 0;
3417 victim->animTarget = staggerbackhighanim;
3418 victim->targetyaw = targetyaw + 180;
3420 if (!Tutorial::active) {
3421 emit_sound_at(landsound2, victim->coords, 128.);
3423 victim->Puff(abdomen);
3424 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3431 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3432 if (animCurrent == spinkickreversalanim && currentFrame().label == 7) {
3441 if (!Tutorial::active) {
3442 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3444 if (PersonType::types[creature].hasClaws) {
3445 emit_sound_at(clawslicesound, victim->coords, 128);
3447 victim->DoBloodBig(2 / victim->armorhigh, 170);
3451 relative = victim->coords - oldcoords;
3453 Normalise(&relative);
3454 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3455 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3457 victim->jointVel(abdomen) += relative * damagemult * 200;
3458 victim->Puff(abdomen);
3459 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3461 award_bonus(id, Reversal);
3464 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3465 if (victim->hasWeapon() && victim->num_weapons > 0) {
3466 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3467 takeWeapon(victim->weaponids[victim->weaponactive]);
3468 victim->num_weapons--;
3469 if (victim->num_weapons > 0) {
3470 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3472 victim->weaponactive = -1;
3477 if (animCurrent == staffhitreversalanim && currentFrame().label == 5) {
3486 emit_sound_at(whooshhitsound, victim->coords, 128.);
3489 relative = victim->coords - oldcoords;
3491 Normalise(&relative);
3492 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3493 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3495 victim->jointVel(abdomen) += relative * damagemult * 200;
3497 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3500 if (animCurrent == staffspinhitreversalanim && currentFrame().label == 7) {
3510 award_bonus(id, staffreversebonus);
3512 if (!Tutorial::active) {
3513 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3516 award_bonus(id, staffreversebonus); // Huh, again?
3519 relative = victim->coords - oldcoords;
3521 Normalise(&relative);
3522 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3523 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3525 victim->jointVel(abdomen) += relative * damagemult * 200;
3527 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3530 if (animCurrent == upunchreversalanim && currentFrame().label == 7) {
3536 Normalise(&relative);
3538 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3539 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3541 victim->jointVel(lefthand) *= .1;
3542 victim->jointVel(leftwrist) *= .2;
3543 victim->jointVel(leftelbow) *= .5;
3544 victim->jointVel(leftshoulder) *= .7;
3545 victim->jointVel(righthand) *= .1;
3546 victim->jointVel(rightwrist) *= .2;
3547 victim->jointVel(rightelbow) *= .5;
3548 victim->jointVel(rightshoulder) *= .7;
3550 victim->Puff(abdomen);
3551 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3553 award_bonus(id, Reversal);
3557 doslice = (weapons[weaponids[0]].getType() != staff);
3559 doslice = PersonType::types[creature].hasClaws;
3563 emit_sound_at(clawslicesound, victim->coords, 128.);
3565 victim->DoBloodBig(2 / victim->armorhigh, 175);
3567 victim->DoBloodBig(2 / victim->armorhigh, 225);
3568 emit_sound_at(knifeslicesound, victim->coords);
3569 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3570 weapons[weaponids[weaponactive]].bloody = 1;
3572 weapons[weaponids[weaponactive]].blooddrip += 3;
3577 if (animCurrent == swordslashreversalanim && currentFrame().label == 7) {
3583 Normalise(&relative);
3585 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3586 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3588 victim->jointVel(lefthand) *= .1 - 1;
3589 victim->jointVel(leftwrist) *= .2 - 1;
3590 victim->jointVel(leftelbow) *= .5 - 1;
3591 victim->jointVel(leftshoulder) *= .7 - 1;
3592 victim->jointVel(righthand) *= .1 - 1;
3593 victim->jointVel(rightwrist) *= .2 - 1;
3594 victim->jointVel(rightelbow) *= .5 - 1;
3595 victim->jointVel(rightshoulder) *= .7 - 1;
3597 award_bonus(id, swordreversebonus);
3600 if (hasvictim && animCurrent == knifeslashreversalanim && currentFrame().label == 7) {
3609 if (!Tutorial::active) {
3610 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3614 relative = victim->coords - oldcoords;
3616 Normalise(&relative);
3617 relative = DoRotation(relative, 0, -90, 0);
3618 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3619 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3621 victim->jointVel(abdomen) += relative * damagemult * 200;
3622 victim->Puff(abdomen);
3623 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3625 award_bonus(id, Reversal);
3628 if (hasvictim && animCurrent == sneakattackanim && currentFrame().label == 7) {
3631 victim->skeleton.spinny = 0;
3633 relative = facing * -1;
3635 Normalise(&relative);
3636 if (victim->id == 0) {
3639 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3640 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3642 victim->damage = victim->damagetolerance;
3643 victim->permanentdamage = victim->damagetolerance - 1;
3646 doslice = (weapons[weaponids[0]].getType() != staff);
3648 doslice = PersonType::types[creature].hasClaws;
3652 emit_sound_at(clawslicesound, victim->coords, 128.);
3654 victim->DoBloodBig(2, 175);
3656 victim->DoBloodBig(200, 225);
3657 emit_sound_at(knifeslicesound, victim->coords);
3659 weapons[weaponids[weaponactive]].bloody = 2;
3661 weapons[weaponids[weaponactive]].blooddrip += 5;
3664 award_bonus(id, spinecrusher);
3667 if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 5) {
3668 if (hasWeapon() && victim->bloodloss < victim->damagetolerance) {
3670 if (animTarget == knifefollowanim) {
3671 victim->DoBloodBig(200, 210);
3673 if (animTarget == knifesneakattackanim) {
3674 XYZ footvel, footpoint;
3676 footpoint = weapons[weaponids[0]].tippoint;
3678 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3680 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3681 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3682 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3683 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3684 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3685 victim->DoBloodBig(200, 195);
3686 award_bonus(id, tracheotomy);
3688 if (animTarget == knifefollowanim) {
3689 award_bonus(id, Stabbonus);
3690 XYZ footvel, footpoint;
3692 footpoint = weapons[weaponids[0]].tippoint;
3694 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3696 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3697 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3698 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3699 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3700 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3702 victim->bloodloss += 10000;
3703 victim->velocity = 0;
3704 emit_sound_at(fleshstabsound, victim->coords);
3706 weapons[weaponids[weaponactive]].bloody = 2;
3708 weapons[weaponids[weaponactive]].blooddrip += 5;
3712 if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 6) {
3714 victim->velocity = 0;
3715 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3716 victim->skeleton.joints[i].velocity = 0;
3718 if (animTarget == knifefollowanim) {
3720 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3721 victim->skeleton.joints[i].velocity = 0;
3724 if (hasWeapon() && Animation::animations[victim->animTarget].attack != reversal) {
3725 emit_sound_at(fleshstabremovesound, victim->coords);
3727 weapons[weaponids[weaponactive]].bloody = 2;
3729 weapons[weaponids[weaponactive]].blooddrip += 5;
3731 XYZ footvel, footpoint;
3733 footpoint = weapons[weaponids[0]].tippoint;
3735 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3737 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3738 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3739 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3740 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3741 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3745 if (hasvictim && (animCurrent == swordsneakattackanim) && currentFrame().label == 5) {
3746 if (hasWeapon() && victim->bloodloss < victim->damagetolerance) {
3747 award_bonus(id, backstab);
3751 XYZ footvel, footpoint;
3753 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3755 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3757 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3758 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3759 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3760 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3761 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3762 victim->DoBloodBig(200, 180);
3763 victim->DoBloodBig(200, 215);
3764 victim->bloodloss += 10000;
3765 victim->velocity = 0;
3766 emit_sound_at(fleshstabsound, victim->coords);
3768 weapons[weaponids[weaponactive]].bloody = 2;
3770 weapons[weaponids[weaponactive]].blooddrip += 5;
3774 if (hasvictim && animCurrent == swordsneakattackanim && currentFrame().label == 6) {
3776 victim->velocity = 0;
3777 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3778 victim->skeleton.joints[i].velocity = 0;
3781 emit_sound_at(fleshstabremovesound, victim->coords);
3783 weapons[weaponids[weaponactive]].bloody = 2;
3785 weapons[weaponids[weaponactive]].blooddrip += 5;
3787 XYZ footvel, footpoint;
3789 footpoint = weapons[weaponids[0]].tippoint;
3791 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3793 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3794 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3795 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3796 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3797 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3801 if (animCurrent == sweepreversalanim && currentFrame().label == 7) {
3811 if (!Tutorial::active) {
3812 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3817 doslice = (weapons[weaponids[0]].getType() != staff);
3819 doslice = PersonType::types[creature].hasClaws;
3823 emit_sound_at(clawslicesound, victim->coords, 128.);
3825 victim->DoBloodBig(2 / victim->armorhead, 175);
3827 victim->DoBloodBig(2 / victim->armorhead, 225);
3828 emit_sound_at(knifeslicesound, victim->coords);
3829 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3830 weapons[weaponids[weaponactive]].bloody = 1;
3832 weapons[weaponids[weaponactive]].blooddrip += 3;
3836 award_bonus(id, Reversal);
3841 relative = facing * -1;
3843 Normalise(&relative);
3844 relative = DoRotation(relative, 0, 90, 0);
3846 Normalise(&relative);
3847 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3848 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3850 victim->jointVel(head) += relative * damagemult * 200;
3851 if (victim->damage < victim->damagetolerance - 100) {
3852 victim->velocity = relative * 200;
3854 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3855 victim->velocity = 0;
3858 if (animCurrent == sweepreversalanim && ((currentFrame().label == 9 && victim->damage < victim->damagetolerance) || (currentFrame().label == 7 && victim->damage > victim->damagetolerance))) {
3862 relative = facing * -1;
3864 Normalise(&relative);
3865 relative = DoRotation(relative, 0, 90, 0);
3867 Normalise(&relative);
3868 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3869 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3871 victim->jointVel(head) += relative * damagemult * 200;
3874 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
3875 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3876 award_bonus(id, reverseko);
3882 if (frameTarget >= int(Animation::animations[animCurrent].frames.size())) {
3885 animTarget = getIdle();
3886 FootLand(leftfoot, 1);
3887 FootLand(rightfoot, 1);
3889 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3890 animTarget = rollanim;
3892 emit_sound_at(movewhooshsound, coords, 128.);
3894 if (animCurrent == staggerbackhighanim) {
3895 animTarget = getIdle();
3897 if (animCurrent == staggerbackhardanim) {
3898 animTarget = getIdle();
3900 if (animCurrent == removeknifeanim) {
3901 animTarget = getIdle();
3903 if (animCurrent == crouchremoveknifeanim) {
3904 animTarget = getCrouch();
3906 if (animCurrent == backhandspringanim) {
3907 animTarget = getIdle();
3909 if (animCurrent == dodgebackanim) {
3910 animTarget = getIdle();
3912 if (animCurrent == drawleftanim) {
3913 animTarget = getIdle();
3915 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3916 animTarget = getIdle();
3917 if (animCurrent == crouchdrawrightanim) {
3918 animTarget = getCrouch();
3922 emit_sound_at(knifedrawsound, coords, 128.);
3923 } else if (weaponactive == 0) {
3925 if (num_weapons == 2) {
3927 buffer = weaponids[0];
3928 weaponids[0] = weaponids[1];
3929 weaponids[1] = buffer;
3931 emit_sound_at(knifesheathesound, coords, 128.);
3934 if (animCurrent == rollanim) {
3935 animTarget = getCrouch();
3936 FootLand(leftfoot, 1);
3937 FootLand(rightfoot, 1);
3940 if (animTarget == walljumprightkickanim) {
3943 if (animTarget == walljumpleftkickanim) {
3946 animTarget = jumpdownanim;
3948 if (animCurrent == climbanim) {
3949 animTarget = getCrouch();
3951 coords += facing * .1;
3952 if (!isnormal(coords.x)) {
3963 if (animTarget == rabbitkickreversalanim) {
3964 animTarget = getCrouch();
3967 if (animTarget == jumpreversalanim) {
3968 animTarget = getCrouch();
3971 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3972 if (attackkeydown && animTarget != walljumpfrontanim) {
3974 float closestdist = -1;
3976 if (Person::players.size() > 1) {
3977 for (unsigned i = 0; i < Person::players.size(); i++) {
3978 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3979 distance = distsq(&Person::players[i]->coords, &coords);
3980 if (closestdist == -1 || distance < closestdist) {
3981 closestdist = distance;
3987 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3988 victim = Person::players[closest];
3989 animTarget = walljumprightkickanim;
3991 XYZ rotatetarget = victim->coords - coords;
3992 Normalise(&rotatetarget);
3993 yaw = -asin(0 - rotatetarget.x);
3995 if (rotatetarget.z < 0) {
3998 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3999 velocity = (victim->coords - coords) * 4;
4004 if (animTarget == walljumpbackanim) {
4005 animTarget = backflipanim;
4007 velocity = facing * -8;
4010 resume_stream(whooshsound);
4013 if (animTarget == walljumprightanim) {
4014 animTarget = rightflipanim;
4018 velocity = DoRotation(facing, 0, 30, 0) * -8;
4021 if (animTarget == walljumpfrontanim) {
4022 animTarget = frontflipanim;
4026 velocity = facing * 8;
4030 resume_stream(whooshsound);
4033 if (animTarget == walljumpleftanim) {
4034 if (attackkeydown) {
4036 float closestdist = -1;
4038 if (Person::players.size() > 1) {
4039 for (unsigned i = 0; i < Person::players.size(); i++) {
4040 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4041 distance = distsq(&Person::players[i]->coords, &coords);
4042 if (closestdist == -1 || distance < closestdist) {
4043 closestdist = distance;
4049 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4050 victim = Person::players[closest];
4051 animTarget = walljumpleftkickanim;
4053 XYZ rotatetarget = victim->coords - coords;
4054 Normalise(&rotatetarget);
4055 yaw = -asin(0 - rotatetarget.x);
4057 if (rotatetarget.z < 0) {
4060 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4061 velocity = (victim->coords - coords) * 4;
4066 if (animTarget != walljumpleftkickanim) {
4067 animTarget = leftflipanim;
4071 velocity = DoRotation(facing, 0, -30, 0) * -8;
4075 resume_stream(whooshsound);
4078 if (animTarget == sneakattackanim) {
4079 animCurrent = getCrouch();
4080 animTarget = getCrouch();
4087 transspeed = 1000000;
4088 targetheadyaw += 180;
4089 coords -= facing * .7;
4091 coords.y = terrain.getHeight(coords.x, coords.z);
4096 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4097 animTarget = getIdle();
4100 coords.y = terrain.getHeight(coords.x, coords.z);
4105 if (animCurrent == knifefollowanim) {
4106 animTarget = getIdle();
4109 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4110 float ycoords = oldcoords.y;
4111 animTarget = getStop();
4116 transspeed = 1000000;
4117 targetheadyaw += 180;
4118 if (!isnormal(coords.x)) {
4121 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4122 oldcoords = coords + facing * .5;
4123 } else if (animCurrent == sweepreversalanim) {
4124 oldcoords = coords + facing * 1.1;
4125 } else if (animCurrent == upunchreversalanim) {
4126 oldcoords = coords + facing * 1.5;
4129 targetheadyaw += 180;
4132 } else if (animCurrent == knifeslashreversalanim) {
4133 oldcoords = coords + facing * .5;
4136 targetheadyaw += 90;
4139 } else if (animCurrent == staffspinhitreversalanim) {
4142 targetheadyaw += 180;
4147 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4149 oldcoords.y = ycoords;
4151 currentoffset = coords - oldcoords;
4157 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4162 if (Animation::animations[animTarget].attack == reversed) {
4164 if (animTarget == sweepreversedanim) {
4167 animTarget = backhandspringanim;
4169 emit_sound_at(landsound, coords, 128);
4171 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4172 animTarget = rollanim;
4175 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4176 coords.y = oldcoords.y;
4178 if (animCurrent == knifeslashreversedanim) {
4179 animTarget = rollanim;
4184 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4185 coords.y = oldcoords.y;
4189 animTarget = jumpdownanim;
4192 animTarget = getIdle();
4194 if (wasLandhard()) {
4195 animTarget = getIdle();
4197 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4198 animTarget = getIdle();
4200 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4201 coords.y = oldcoords.y;
4202 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4203 targetoffset.y = coords.y;
4205 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4207 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4208 currentoffset.y -= (coords.y - targetoffset.y);
4209 coords.y = targetoffset.y;
4211 normalsupdatedelay = 0;
4213 if (animCurrent == upunchanim) {
4214 animTarget = getStop();
4215 normalsupdatedelay = 0;
4218 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4222 if (num_weapons > 0) {
4223 if (weapons[0].getType() == staff) {
4232 rabbitkickragdoll = 1;
4234 if (animCurrent == rabbitkickreversedanim) {
4240 skeleton.spinny = 0;
4241 SolidHitBonus(!id); // FIXME: tricky id
4245 animTarget = rollanim;
4248 pause_sound(whooshsound);
4253 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4257 skeleton.spinny = 0;
4259 if (animCurrent == jumpreversedanim) {
4265 skeleton.spinny = 0;
4266 SolidHitBonus(!id); // FIXME: tricky id
4270 animTarget = rollanim;
4271 coords += facing * 2;
4273 pause_sound(whooshsound);
4279 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) {
4280 animTarget = getupfromfrontanim;
4282 } else if (Animation::animations[animCurrent].attack == normalattack) {
4283 animTarget = getIdle();
4286 if (animCurrent == blockhighleftanim && !isPlayerControlled()) {
4287 animTarget = blockhighleftstrikeanim;
4289 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4290 animTarget = getIdle();
4293 if (animCurrent == spinkickanim && victim->skeleton.free) {
4294 if (creature == rabbittype) {
4295 animTarget = fightidleanim;
4301 if (isIdle() && !wasIdle()) {
4302 normalsupdatedelay = 0;
4305 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4306 animTarget = jumpdownanim;
4309 if (!skeleton.free) {
4311 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4312 if (!isRun() || !wasRun()) {
4313 if (targetFrame().speed > currentFrame().speed) {
4314 target += multiplier * targetFrame().speed * speed * 2;
4316 if (targetFrame().speed <= currentFrame().speed) {
4317 target += multiplier * currentFrame().speed * speed * 2;
4320 if (isRun() && wasRun()) {
4322 tempspeed = velspeed;
4323 if (tempspeed < 10 * speedmult) {
4324 tempspeed = 10 * speedmult;
4326 /* FIXME - mixed of target and current here, is that intended? */
4327 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4329 } else if (transspeed) {
4330 target += multiplier * transspeed * speed * 2;
4332 if (!isRun() || !wasRun()) {
4333 if (targetFrame().speed > currentFrame().speed) {
4334 target += multiplier * targetFrame().speed * 2;
4336 if (targetFrame().speed <= currentFrame().speed) {
4337 target += multiplier * currentFrame().speed * 2;
4342 if (animCurrent != animTarget) {
4343 target = (target + oldtarget) / 2;
4347 frameCurrent = frameTarget;
4351 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4352 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4356 rot = targetrot * target;
4357 yaw += rot - oldrot;
4364 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4366 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4367 skeleton.joints[i].position = currentFrame().joints[i].position;
4370 skeleton.FindForwards();
4372 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4373 if (skeleton.muscles[i].visible) {
4374 skeleton.FindRotationMuscle(i, animTarget);
4377 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4378 if (skeleton.muscles[i].visible) {
4379 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4380 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4382 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4383 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4385 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4386 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4392 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4393 skeleton.joints[i].position = targetFrame().joints[i].position;
4396 skeleton.FindForwards();
4398 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4399 if (skeleton.muscles[i].visible) {
4400 skeleton.FindRotationMuscle(i, animTarget);
4403 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4404 if (skeleton.muscles[i].visible) {
4405 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4406 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4408 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4409 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4411 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4412 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4414 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4415 skeleton.muscles[i].newrotate3 -= 360;
4417 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4418 skeleton.muscles[i].newrotate3 += 360;
4420 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4421 skeleton.muscles[i].newrotate2 -= 360;
4423 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4424 skeleton.muscles[i].newrotate2 += 360;
4426 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4427 skeleton.muscles[i].newrotate1 -= 360;
4429 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4430 skeleton.muscles[i].newrotate1 += 360;
4436 oldanimCurrent = animCurrent;
4437 oldanimTarget = animTarget;
4438 oldframeTarget = frameTarget;
4439 oldframeCurrent = frameCurrent;
4441 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4442 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4443 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4445 offset = currentoffset * (1 - target) + targetoffset * target;
4446 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4447 if (skeleton.muscles[i].visible) {
4448 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4449 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4450 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4455 if (isLanding() && landhard) {
4459 animTarget = getLandhard();
4472 void Person::DoStuff()
4474 static XYZ terrainnormal;
4475 static XYZ flatfacing;
4476 static XYZ flatvelocity;
4477 static float flatvelspeed;
4478 static int bloodsize;
4479 static int startx, starty, endx, endy;
4480 static GLubyte color;
4481 static XYZ bloodvel;
4483 onfiredelay -= multiplier;
4484 if (onfiredelay < 0 && onfire) {
4485 if (Random() % 2 == 0) {
4491 crouchkeydowntime += multiplier;
4492 if (!crouchkeydown) {
4493 crouchkeydowntime = 0;
4495 jumpkeydowntime += multiplier;
4496 if (!jumpkeydown && skeleton.free) {
4497 jumpkeydowntime = 0;
4500 if (hostile || damage > 0 || bloodloss > 0) {
4504 if (isIdle() || isRun()) {
4508 if (num_weapons == 1 && hasWeapon()) {
4513 blooddimamount -= multiplier * .3;
4515 speechdelay -= multiplier;
4516 texupdatedelay -= multiplier;
4517 interestdelay -= multiplier;
4518 flamedelay -= multiplier;
4519 parriedrecently -= multiplier;
4521 victim = this->shared_from_this();
4526 speed = 1.1 * speedmult;
4528 speed = 1.0 * speedmult;
4530 if (!skeleton.free) {
4531 rabbitkickragdoll = 0;
4536 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4539 if (id != 0 && creature == wolftype && difficulty == 2) {
4541 if (aitype != passivetype) {
4543 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) {
4550 if (animTarget == wolfrunninganim && !superruntoggle) {
4551 animTarget = getRun();
4555 if (!hasWeapon() && num_weapons > 0) {
4556 if (weapons[weaponids[0]].getType() == staff) {
4562 burnt += multiplier;
4567 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4569 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4576 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4577 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4581 while (flamedelay < 0 && onfire) {
4583 int howmany = fabs(Random() % (skeleton.joints.size()));
4584 if (skeleton.free) {
4585 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4586 flatfacing = skeleton.joints[howmany].position * scale + coords;
4588 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4589 flatvelocity = (coords - oldcoords) / multiplier / 2;
4591 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4594 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4596 int howmany = fabs(Random() % (skeleton.joints.size()));
4597 if (skeleton.free) {
4598 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4599 flatfacing = skeleton.joints[howmany].position * scale + coords;
4601 flatvelocity = (coords - oldcoords) / multiplier / 2;
4602 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4604 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4608 bleeding -= multiplier * .3;
4609 if (bloodtoggle == 2) {
4610 skeleton.drawmodel.textureptr.bind();
4611 if ((bleeding <= 0) && (detail != 2)) {
4617 if (neckspurtamount > 0) {
4618 neckspurtamount -= multiplier;
4619 neckspurtdelay -= multiplier * 3;
4620 neckspurtparticledelay -= multiplier * 3;
4621 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4624 if (skeleton.free) {
4625 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4626 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4627 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4629 bloodvel.z = 5 * neckspurtamount;
4630 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4631 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4632 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4634 neckspurtparticledelay = .05;
4636 if (neckspurtdelay < 0) {
4641 if (deathbleeding > 0 && dead != 2) {
4642 if (deathbleeding < 5) {
4643 bleeddelay -= deathbleeding * multiplier / 4;
4645 bleeddelay -= 5 * multiplier / 4;
4647 if (bleeddelay < 0 && bloodtoggle) {
4652 if (skeleton.free) {
4653 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4654 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4656 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4657 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4661 bloodloss += deathbleeding * multiplier * 80;
4662 deathbleeding -= multiplier * 1.6;
4663 if (deathbleeding < 0) {
4666 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4668 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4669 weapons[weaponids[0]].velocity.x += .01;
4672 weaponids[0] = weaponids[num_weapons];
4673 if (weaponstuck == num_weapons) {
4678 for (unsigned i = 0; i < Person::players.size(); i++) {
4679 Person::players[i]->wentforweapon = 0;
4687 if (!dead && creature == wolftype) {
4688 award_bonus(0, Wolfbonus);
4691 if (animTarget == knifefollowedanim && !skeleton.free) {
4692 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4693 skeleton.joints[i].velocity = 0;
4694 skeleton.joints[i].velocity.y = -2;
4697 if (id != 0 && unconscioustime > .1) {
4705 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4706 texupdatedelay = .12;
4708 bloodsize = 5 - realtexdetail;
4712 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4713 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4714 endx = startx + bloodsize;
4715 endy = starty + bloodsize;
4725 if (endx > skeleton.skinsize - 1) {
4726 endx = skeleton.skinsize - 1;
4729 if (endy > skeleton.skinsize - 1) {
4730 endy = skeleton.skinsize - 1;
4733 if (endx < startx) {
4736 if (endy < starty) {
4740 for (int i = startx; i < endx; i++) {
4741 for (int j = starty; j < endy; j++) {
4742 if (Random() % 2 == 0) {
4743 color = Random() % 85 + 170;
4744 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4745 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4747 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4748 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4753 skeleton.drawmodel.textureptr.bind();
4757 if (skeleton.free) {
4758 bleedx += 4 * direction / realtexdetail;
4760 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4762 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4765 bleedy -= 4 / realtexdetail;
4767 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4769 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4774 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4775 righthandmorphness = targetrighthandmorphness;
4776 righthandmorphstart = righthandmorphend;
4777 } else if (righthandmorphness > targetrighthandmorphness) {
4778 righthandmorphness -= multiplier * 4;
4779 } else if (righthandmorphness < targetrighthandmorphness) {
4780 righthandmorphness += multiplier * 4;
4783 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4784 lefthandmorphness = targetlefthandmorphness;
4785 lefthandmorphstart = lefthandmorphend;
4786 } else if (lefthandmorphness > targetlefthandmorphness) {
4787 lefthandmorphness -= multiplier * 4;
4788 } else if (lefthandmorphness < targetlefthandmorphness) {
4789 lefthandmorphness += multiplier * 4;
4792 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4793 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4794 tailmorphness = targettailmorphness;
4795 tailmorphstart = tailmorphend;
4796 } else if (tailmorphness > targettailmorphness) {
4797 tailmorphness -= multiplier * 10;
4798 } else if (tailmorphness < targettailmorphness) {
4799 tailmorphness += multiplier * 10;
4803 if (creature == wolftype) {
4804 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4805 tailmorphness = targettailmorphness;
4806 tailmorphstart = tailmorphend;
4807 } else if (tailmorphness > targettailmorphness) {
4808 tailmorphness -= multiplier * 2;
4809 } else if (tailmorphness < targettailmorphness) {
4810 tailmorphness += multiplier * 2;
4814 if (headmorphend == 3 || headmorphstart == 3) {
4815 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4816 headmorphness = targetheadmorphness;
4817 headmorphstart = headmorphend;
4818 } else if (headmorphness > targetheadmorphness) {
4819 headmorphness -= multiplier * 7;
4820 } else if (headmorphness < targetheadmorphness) {
4821 headmorphness += multiplier * 7;
4823 } else if (headmorphend == 5 || headmorphstart == 5) {
4824 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4825 headmorphness = targetheadmorphness;
4826 headmorphstart = headmorphend;
4827 } else if (headmorphness > targetheadmorphness) {
4828 headmorphness -= multiplier * 10;
4829 } else if (headmorphness < targetheadmorphness) {
4830 headmorphness += multiplier * 10;
4833 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4834 headmorphness = targetheadmorphness;
4835 headmorphstart = headmorphend;
4836 } else if (headmorphness > targetheadmorphness) {
4837 headmorphness -= multiplier * 4;
4838 } else if (headmorphness < targetheadmorphness) {
4839 headmorphness += multiplier * 4;
4843 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4844 chestmorphness = targetchestmorphness;
4845 chestmorphstart = chestmorphend;
4846 } else if (chestmorphness > targetchestmorphness) {
4847 chestmorphness -= multiplier;
4848 } else if (chestmorphness < targetchestmorphness) {
4849 chestmorphness += multiplier;
4852 if (dead != 2 && howactive <= typesleeping) {
4853 if (chestmorphstart == 0 && chestmorphend == 0) {
4855 targetchestmorphness = 1;
4858 if (chestmorphstart != 0 && chestmorphend != 0) {
4860 targetchestmorphness = 1;
4862 if (environment == snowyenvironment) {
4865 if (skeleton.free) {
4866 footvel = skeleton.specialforward[0] * -1;
4867 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4869 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4870 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4872 if (animTarget == sleepanim) {
4873 footvel = DoRotation(footvel, 0, 90, 0);
4875 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4879 if (!dead && howactive < typesleeping) {
4880 blinkdelay -= multiplier * 2;
4881 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4883 targetheadmorphness = 1;
4885 blinkdelay = (float)(abs(Random() % 40)) / 5;
4887 if (headmorphstart == 3 && headmorphend == 3) {
4889 targetheadmorphness = 1;
4894 twitchdelay -= multiplier * 1.5;
4895 if (animTarget != hurtidleanim) {
4896 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4898 targetheadmorphness = 1;
4900 twitchdelay = (float)(abs(Random() % 40)) / 5;
4902 if (headmorphstart == 5 && headmorphend == 5) {
4904 targetheadmorphness = 1;
4908 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4909 twitchdelay3 -= multiplier * 1;
4910 if (Random() % 2 == 0) {
4911 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4912 righthandmorphness = 0;
4913 targetrighthandmorphness = 1;
4914 righthandmorphend = 1;
4915 if (Random() % 2 == 0) {
4916 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4919 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4920 righthandmorphness = 0;
4921 targetrighthandmorphness = 1;
4922 righthandmorphend = 0;
4925 if (Random() % 2 == 0) {
4926 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4927 lefthandmorphness = 0;
4928 targetlefthandmorphness = 1;
4929 lefthandmorphend = 1;
4930 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4932 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4933 lefthandmorphness = 0;
4934 targetlefthandmorphness = 1;
4935 lefthandmorphend = 0;
4941 if (creature == rabbittype) {
4942 if (howactive < typesleeping) {
4943 twitchdelay2 -= multiplier * 1.5;
4945 twitchdelay2 -= multiplier * 0.5;
4947 if (howactive <= typesleeping) {
4948 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4950 targettailmorphness = 1;
4952 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4954 if (tailmorphstart == 1 && tailmorphend == 1) {
4956 targettailmorphness = 1;
4959 if (tailmorphstart == 2 && tailmorphend == 2) {
4961 targettailmorphness = 1;
4968 if (creature == wolftype) {
4969 twitchdelay2 -= multiplier * 1.5;
4970 if (tailmorphend != 0) {
4971 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4973 targettailmorphness = 1;
4978 if (tailmorphend != 5) {
4979 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4981 targettailmorphness = 1;
4986 if (twitchdelay2 <= 0) {
4987 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4989 targettailmorphness = 1;
4992 if (tailmorphstart == 1 && tailmorphend == 1) {
4994 targettailmorphness = 1;
4997 if (tailmorphstart == 2 && tailmorphend == 2) {
4999 targettailmorphness = 1;
5002 if (tailmorphstart == 3 && tailmorphend == 3) {
5004 targettailmorphness = 1;
5007 if (tailmorphstart == 4 && tailmorphend == 4) {
5009 targettailmorphness = 1;
5016 unconscioustime = 0;
5019 if (dead == 1 || howactive == typesleeping) {
5020 unconscioustime += multiplier;
5021 //If unconscious, close eyes and mouth
5022 if (righthandmorphend != 0) {
5023 righthandmorphness = 0;
5025 righthandmorphend = 0;
5026 targetrighthandmorphness = 1;
5028 if (lefthandmorphend != 0) {
5029 lefthandmorphness = 0;
5031 lefthandmorphend = 0;
5032 targetlefthandmorphness = 1;
5034 if (headmorphend != 3 && headmorphend != 5) {
5038 targetheadmorphness = 1;
5041 if (howactive > typesleeping) {
5044 if (bloodtoggle && !bled) {
5045 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5046 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5047 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5048 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5052 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5058 if (dead == 2 || howactive > typesleeping) {
5059 //If dead, open mouth and hands
5060 if (righthandmorphend != 0) {
5061 righthandmorphness = 0;
5063 righthandmorphend = 0;
5064 targetrighthandmorphness = 1;
5066 if (lefthandmorphend != 0) {
5067 lefthandmorphness = 0;
5069 lefthandmorphend = 0;
5070 targetlefthandmorphness = 1;
5072 if (headmorphend != 2) {
5076 targetheadmorphness = 1;
5079 if (stunned > 0 && !dead && headmorphend != 2) {
5080 if (headmorphend != 4) {
5084 targetheadmorphness = 1;
5087 if (damage > damagetolerance && !dead) {
5090 unconscioustime = 0;
5092 if (creature == wolftype) {
5093 award_bonus(0, Wolfbonus);
5099 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5100 weapons[weaponids[0]].velocity.x += .01;
5103 weaponids[0] = weaponids[num_weapons];
5104 if (weaponstuck == num_weapons) {
5109 for (unsigned i = 0; i < Person::players.size(); i++) {
5110 Person::players[i]->wentforweapon = 0;
5114 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5123 damage -= multiplier * 13;
5124 permanentdamage -= multiplier * 4;
5125 if (isIdle() || isCrouch()) {
5126 permanentdamage -= multiplier * 4;
5132 if (permanentdamage < 0) {
5133 permanentdamage = 0;
5135 if (superpermanentdamage < 0) {
5136 superpermanentdamage = 0;
5138 if (permanentdamage < superpermanentdamage) {
5139 permanentdamage = superpermanentdamage;
5141 if (damage < permanentdamage) {
5142 damage = permanentdamage;
5144 if (dead == 1 && damage < damagetolerance) {
5148 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5149 skeleton.joints[i].velocity = 0;
5152 if (permanentdamage > damagetolerance && dead != 2) {
5156 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5157 weapons[weaponids[0]].velocity.x += .01;
5160 weaponids[0] = weaponids[num_weapons];
5161 if (weaponstuck == num_weapons) {
5166 for (unsigned i = 0; i < Person::players.size(); i++) {
5167 Person::players[i]->wentforweapon = 0;
5173 if (!dead && creature == wolftype) {
5174 award_bonus(0, Wolfbonus);
5177 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5178 award_bonus(id, touchofdeath);
5180 if (id != 0 && unconscioustime > .1) {
5188 emit_sound_at(breaksound, coords);
5191 if (skeleton.free == 1) {
5193 pause_sound(whooshsound);
5197 //If knocked over, open hands and close mouth
5198 if (righthandmorphend != 0) {
5199 righthandmorphness = 0;
5201 righthandmorphend = 0;
5202 targetrighthandmorphness = 1;
5204 if (lefthandmorphend != 0) {
5205 lefthandmorphness = 0;
5207 lefthandmorphend = 0;
5208 targetlefthandmorphness = 1;
5210 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5211 if (headmorphend != 0) {
5215 targetheadmorphness = 1;
5219 skeleton.DoGravity(&scale);
5221 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5222 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5223 award_bonus(id, deepimpact);
5225 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5229 if (!skeleton.joints.empty()) {
5230 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5231 average += skeleton.joints[j].position;
5233 average /= skeleton.joints.size();
5234 coords += average * scale;
5235 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5236 skeleton.joints[j].position -= average;
5238 average /= multiplier;
5242 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5243 velocity += skeleton.joints[i].velocity * scale;
5245 velocity /= skeleton.joints.size();
5247 if (!isnormal(velocity.x) && velocity.x) {
5251 if (findLength(&average) < 10 && dead && skeleton.free) {
5252 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5253 if (skeleton.longdead > 2000) {
5254 if (skeleton.longdead > 6000) {
5256 pause_sound(whooshsound);
5262 if (dead == 2 && bloodloss < damagetolerance) {
5264 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5266 if (bloodtoggle && !bled) {
5267 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5268 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5269 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5270 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5271 float size = .2 * 1.2;
5274 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5279 if (dead == 2 && bloodloss >= damagetolerance) {
5281 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5282 if (bleeding <= 0) {
5285 if (bloodtoggle && !bled) {
5286 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5287 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5288 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5289 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5293 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5301 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5302 bool canrecover = 1;
5303 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5304 startpoint = coords;
5307 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5310 if (velocity.y < -30) {
5313 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5314 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5315 colviewer = startpoint;
5316 coltarget = endpoint;
5317 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5327 terrainnormal = jointPos(groin) - jointPos(abdomen);
5328 if (joint(groin).locked && joint(abdomen).locked) {
5329 terrainnormal = jointPos(groin) - jointPos(abdomen);
5330 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5332 if (joint(abdomen).locked && joint(neck).locked) {
5333 terrainnormal = jointPos(abdomen) - jointPos(neck);
5334 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5336 if (joint(groin).locked && joint(neck).locked) {
5337 terrainnormal = jointPos(groin) - jointPos(neck);
5338 middle = (jointPos(groin) + jointPos(neck)) / 2;
5340 Normalise(&terrainnormal);
5342 targetyaw = -asin(0 - terrainnormal.x);
5343 targetyaw *= 360 / 6.28;
5344 if (terrainnormal.z < 0) {
5345 targetyaw = 180 - targetyaw;
5350 animTarget = flipanim;
5351 crouchtogglekeydown = 1;
5356 animCurrent = tempanim;
5360 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5361 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5362 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5367 if (findLength(&average) < 10 && !dead && skeleton.free) {
5368 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5369 if (skeleton.longdead > (damage + 500) * 1.5) {
5371 pause_sound(whooshsound);
5378 terrainnormal = jointPos(groin) - jointPos(abdomen);
5379 if (joint(groin).locked && joint(abdomen).locked) {
5380 terrainnormal = jointPos(groin) - jointPos(abdomen);
5381 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5383 if (joint(abdomen).locked && joint(neck).locked) {
5384 terrainnormal = jointPos(abdomen) - jointPos(neck);
5385 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5387 if (joint(groin).locked && joint(neck).locked) {
5388 terrainnormal = jointPos(groin) - jointPos(neck);
5389 middle = (jointPos(groin) + jointPos(neck)) / 2;
5391 Normalise(&terrainnormal);
5393 targetyaw = -asin(0 - terrainnormal.x);
5394 targetyaw *= 360 / 6.28;
5395 if (terrainnormal.z < 0) {
5396 targetyaw = 180 - targetyaw;
5400 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5402 if (skeleton.forward.y < 0) {
5403 animTarget = getupfrombackanim;
5407 if (skeleton.forward.y > -.3) {
5408 animTarget = getupfromfrontanim;
5416 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5417 animTarget = rollanim;
5418 targetyaw = lookyaw;
5422 if (forwardkeydown) {
5431 if (forwardkeydown) {
5439 if (!leftkeydown && !rightkeydown) {
5447 if (abs(targettilt2) > 50) {
5450 animCurrent = tempanim;
5453 tilt2 = targettilt2;
5455 if (middle.y > 0 && animTarget != rollanim) {
5456 targetoffset.y = middle.y + 1;
5459 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5460 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5461 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5468 if (num_weapons > 0) {
5469 if (weapons[0].getType() == staff) {
5473 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5474 if (velocity.y > -30) {
5476 tempvelocity = velocity;
5477 Normalise(&tempvelocity);
5478 targetyaw = -asin(0 - tempvelocity.x);
5479 targetyaw *= 360 / 6.28;
5480 if (velocity.z < 0) {
5481 targetyaw = 180 - targetyaw;
5486 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5487 animTarget = rollanim;
5490 animTarget = backhandspringanim;
5496 emit_sound_at(movewhooshsound, coords, 128.);
5498 animCurrent = animTarget;
5499 frameCurrent = frameTarget - 1;
5511 if (skeleton.freefall == 0) {
5516 if (aitype != passivetype || skeleton.free == 1) {
5517 if (findLengthfast(&velocity) > .1) {
5518 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5519 if (Object::objects[i]->type == firetype) {
5520 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) {
5522 if (!Object::objects[i]->onfire) {
5523 emit_sound_at(firestartsound, Object::objects[i]->position);
5525 Object::objects[i]->onfire = 1;
5528 if (Object::objects[i]->onfire) {
5534 if (Object::objects[i]->type == bushtype) {
5535 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) {
5537 if (!Object::objects[i]->onfire) {
5538 emit_sound_at(firestartsound, Object::objects[i]->position);
5540 Object::objects[i]->onfire = 1;
5544 if (Object::objects[i]->onfire) {
5548 if (Object::objects[i]->messedwith <= 0) {
5552 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5555 addEnvSound(coords, 4 * findLength(&velocity));
5559 if (environment == grassyenvironment) {
5560 howmany = findLength(&velocity) * 4;
5562 if (environment == snowyenvironment) {
5563 howmany = findLength(&velocity) * 2;
5566 if (environment != desertenvironment) {
5567 for (int j = 0; j < howmany; j++) {
5568 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5569 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5570 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5573 pos.x += float(abs(Random() % 100) - 50) / 200;
5574 pos.y += float(abs(Random() % 100) - 50) / 200;
5575 pos.z += float(abs(Random() % 100) - 50) / 200;
5576 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);
5577 Sprite::setLastSpriteSpecial(1);
5581 howmany = findLength(&velocity) * 4;
5583 if (environment == snowyenvironment) {
5584 for (int j = 0; j < howmany; j++) {
5585 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5586 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5587 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5590 pos.x += float(abs(Random() % 100) - 50) / 200;
5591 pos.y += float(abs(Random() % 100) - 50) / 200;
5592 pos.z += float(abs(Random() % 100) - 50) / 200;
5593 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5594 Sprite::setLastSpriteSpecial(2);
5599 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5600 Object::objects[i]->roty += velocity.z * multiplier * 6;
5601 Object::objects[i]->messedwith = .5;
5605 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5606 if (Object::objects[i]->pitch == 0) {
5609 tempcoord = coords - Object::objects[i]->position;
5610 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5611 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5612 tempcoord += Object::objects[i]->position;
5614 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) {
5615 if (Object::objects[i]->messedwith <= 0) {
5619 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5622 addEnvSound(coords, 4 * findLength(&velocity));
5626 if (environment == grassyenvironment) {
5627 howmany = findLength(&velocity) * 4;
5629 if (environment == snowyenvironment) {
5630 howmany = findLength(&velocity) * 2;
5633 if (environment != desertenvironment) {
5634 for (int j = 0; j < howmany; j++) {
5635 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5636 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5637 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5639 pos += velocity * .1;
5641 pos.x += float(abs(Random() % 100) - 50) / 150;
5642 pos.y += float(abs(Random() % 100) - 50) / 150;
5643 pos.z += float(abs(Random() % 100) - 50) / 150;
5644 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);
5645 Sprite::setLastSpriteSpecial(1);
5649 howmany = findLength(&velocity) * 4;
5651 if (environment == snowyenvironment) {
5652 for (int j = 0; j < howmany; j++) {
5653 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5654 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5655 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5657 pos += velocity * .1;
5659 pos.x += float(abs(Random() % 100) - 50) / 150;
5660 pos.y += float(abs(Random() % 100) - 50) / 150;
5661 pos.z += float(abs(Random() % 100) - 50) / 150;
5662 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5663 Sprite::setLastSpriteSpecial(2);
5668 Object::objects[i]->messedwith = .5;
5675 if (!skeleton.free) {
5678 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5682 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5686 if (Tutorial::active && id != 0) {
5689 if (play && !isPlayerControlled()) {
5690 int whichsound = -1;
5691 if (speechdelay <= 0) {
5692 unsigned int i = abs(Random() % 4);
5694 whichsound = PersonType::types[creature].soundsTalk[i];
5699 if (whichsound != -1) {
5700 emit_sound_at(whichsound, coords);
5704 if (animTarget == staggerbackhighanim) {
5707 if (animTarget == staggerbackhardanim) {
5710 staggerdelay -= multiplier;
5711 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5714 if (velocity.y < -30 && animTarget == jumpdownanim) {
5717 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5718 animTarget = getIdle();
5722 weaponmissdelay -= multiplier;
5723 highreversaldelay -= multiplier;
5724 lowreversaldelay -= multiplier;
5725 lastcollide -= multiplier;
5726 skiddelay -= multiplier;
5727 if (!isnormal(velocity.x) && velocity.x) {
5730 if (!isnormal(targettilt) && targettilt) {
5733 if (!isnormal(targettilt2) && targettilt2) {
5736 if (!isnormal(targetyaw) && targetyaw) {
5740 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5741 //open hands and close mouth
5742 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5743 righthandmorphness = 0;
5744 righthandmorphend = 0;
5745 targetrighthandmorphness = 1;
5748 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5749 lefthandmorphness = 0;
5750 lefthandmorphend = 0;
5751 targetlefthandmorphness = 1;
5754 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5757 targetheadmorphness = 1;
5761 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) {
5762 //open hands and mouth
5763 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5764 righthandmorphness = 0;
5765 righthandmorphend = 0;
5766 targetrighthandmorphness = 1;
5769 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5770 lefthandmorphness = 0;
5771 lefthandmorphend = 0;
5772 targetlefthandmorphness = 1;
5775 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5778 targetheadmorphness = 1;
5782 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5783 //close hands and mouth
5784 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5785 righthandmorphness = 0;
5786 righthandmorphend = 1;
5787 targetrighthandmorphness = 1;
5790 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5791 lefthandmorphness = 0;
5792 lefthandmorphend = 1;
5793 targetlefthandmorphness = 1;
5796 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5799 targetheadmorphness = 1;
5803 if (animTarget == spinkickanim ||
5804 animTarget == staffspinhitreversalanim ||
5805 animTarget == staffspinhitreversedanim ||
5806 animTarget == staffhitreversalanim ||
5807 animTarget == staffhitreversedanim ||
5808 animTarget == hurtidleanim ||
5809 animTarget == winduppunchanim ||
5810 animTarget == swordslashreversalanim ||
5811 animTarget == swordslashreversedanim ||
5812 animTarget == knifeslashreversalanim ||
5813 animTarget == knifeslashreversedanim ||
5814 animTarget == knifethrowanim ||
5815 animTarget == knifefollowanim ||
5816 animTarget == knifefollowedanim ||
5817 animTarget == killanim ||
5818 animTarget == dropkickanim ||
5819 animTarget == upunchanim ||
5820 animTarget == knifeslashstartanim ||
5821 animTarget == swordslashanim ||
5822 animTarget == staffhitanim ||
5823 animTarget == staffspinhitanim ||
5824 animTarget == staffgroundsmashanim ||
5825 animTarget == spinkickreversalanim ||
5826 animTarget == sweepreversalanim ||
5827 animTarget == lowkickanim ||
5828 animTarget == sweepreversedanim ||
5829 animTarget == rabbitkickreversalanim ||
5830 animTarget == rabbitkickreversedanim ||
5831 animTarget == jumpreversalanim ||
5832 animTarget == jumpreversedanim) {
5833 //close hands and yell
5834 if (righthandmorphend != 1 &&
5835 righthandmorphness == targetrighthandmorphness) {
5836 righthandmorphness = 0;
5837 righthandmorphend = 1;
5838 targetrighthandmorphness = 1;
5841 if (lefthandmorphend != 1 &&
5842 lefthandmorphness == targetlefthandmorphness) {
5843 lefthandmorphness = 0;
5844 lefthandmorphend = 1;
5845 targetlefthandmorphness = 1;
5848 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5851 targetheadmorphness = 1;
5858 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5859 (victim->aitype != searchtype) && (aitype != passivetype) &&
5860 (aitype != searchtype) && (victim->id < Person::players.size())) {
5861 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5865 if (!dead && animTarget != hurtidleanim) {
5866 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5867 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5870 targetheadmorphness = 1;
5876 if (weapons[weaponids[weaponactive]].getType() != staff) {
5877 righthandmorphstart = 1;
5878 righthandmorphend = 1;
5880 if (weapons[weaponids[weaponactive]].getType() == staff) {
5881 righthandmorphstart = 2;
5882 righthandmorphend = 2;
5884 targetrighthandmorphness = 1;
5887 terrainnormal = terrain.getNormal(coords.x, coords.z);
5889 if (Animation::animations[animTarget].attack != reversal) {
5890 if (!isnormal(coords.x)) {
5899 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5900 facing = flatfacing;
5901 ReflectVector(&facing, terrainnormal);
5905 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5907 targettilt2 = -facing.y * 20;
5913 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
5916 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5917 flatvelocity = velocity;
5919 flatvelspeed = findLength(&flatvelocity);
5920 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5921 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5922 if (velocity.y < 0) {
5925 if (velocity.y < 0) {
5928 if (targettilt > 25) {
5931 if (targettilt < -25) {
5936 if (targettilt2 > 45) {
5939 if (targettilt2 < -45) {
5942 if (abs(tilt2 - targettilt2) < multiplier * 400) {
5943 tilt2 = targettilt2;
5944 } else if (tilt2 > targettilt2) {
5945 tilt2 -= multiplier * 400;
5946 } else if (tilt2 < targettilt2) {
5947 tilt2 += multiplier * 400;
5949 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5958 if (!isnormal(targettilt) && targettilt) {
5961 if (!isnormal(targettilt2) && targettilt2) {
5966 if (animTarget == rabbittackleanim) {
5967 velocity += facing * multiplier * speed * 700 * scale;
5968 velspeed = findLength(&velocity);
5969 if (velspeed > speed * 65 * scale) {
5970 velocity /= velspeed;
5971 velspeed = speed * 65 * scale;
5972 velocity *= velspeed;
5974 velocity.y += gravity * multiplier * 20;
5975 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5976 velspeed = findLength(&velocity);
5977 velocity = flatfacing * velspeed;
5979 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5980 if (isRun() || animTarget == rabbitkickanim) {
5981 velocity += facing * multiplier * speed * 700 * scale;
5982 velspeed = findLength(&velocity);
5983 if (velspeed > speed * 45 * scale) {
5984 velocity /= velspeed;
5985 velspeed = speed * 45 * scale;
5986 velocity *= velspeed;
5988 velocity.y += gravity * multiplier * 20;
5989 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5990 velspeed = findLength(&velocity);
5991 if (velspeed < speed * 30 * scale) {
5992 velspeed = speed * 30 * scale;
5994 velocity = flatfacing * velspeed;
5996 } else if (isRun()) {
5997 velocity += facing * multiplier * speed * 700 * scale;
5998 velspeed = findLength(&velocity);
5999 if (velspeed > speed * PersonType::types[creature].maxRunSpeed * scale) {
6000 velocity /= velspeed;
6001 velspeed = speed * PersonType::types[creature].maxRunSpeed * scale;
6002 velocity *= velspeed;
6004 velocity.y += gravity * multiplier * 20;
6005 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6006 velspeed = findLength(&velocity);
6007 velocity = flatfacing * velspeed;
6010 if (animTarget == rollanim && targetFrame().label != 6) {
6011 velocity += facing * multiplier * speed * 700 * scale;
6012 velspeed = findLength(&velocity);
6013 if (velspeed > speed * 45 * scale) {
6014 velocity /= velspeed;
6015 velspeed = speed * 45 * scale;
6016 velocity *= velspeed;
6018 velocity.y += gravity * multiplier * 20;
6019 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6020 velspeed = findLength(&velocity);
6021 velocity = flatfacing * velspeed;
6024 if (animTarget == sneakanim || animTarget == walkanim) {
6025 velocity += facing * multiplier * speed * 700 * scale;
6026 velspeed = findLength(&velocity);
6027 if (velspeed > speed * 12 * scale) {
6028 velocity /= velspeed;
6029 velspeed = speed * 12 * scale;
6030 velocity *= velspeed;
6032 velocity.y += gravity * multiplier * 20;
6033 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6034 velspeed = findLength(&velocity);
6035 velocity = flatfacing * velspeed;
6038 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6039 velocity += facing * multiplier * speed * 700 * scale;
6040 velspeed = findLength(&velocity);
6041 if (velspeed > speed * 2 * scale) {
6042 velocity /= velspeed;
6043 velspeed = speed * 2 * scale;
6044 velocity *= velspeed;
6046 velocity.y += gravity * multiplier * 20;
6047 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6048 velspeed = findLength(&velocity);
6049 velocity = flatfacing * velspeed;
6052 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6053 velocity -= facing * multiplier * speed * 700 * scale;
6054 velspeed = findLength(&velocity);
6055 if (velspeed > speed * 2 * scale) {
6056 velocity /= velspeed;
6057 velspeed = speed * 2 * scale;
6058 velocity *= velspeed;
6060 velocity.y += gravity * multiplier * 20;
6061 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6062 velspeed = findLength(&velocity);
6063 velocity = flatfacing * velspeed * -1;
6066 if (animTarget == fightsidestep) {
6067 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6068 velspeed = findLength(&velocity);
6069 if (velspeed > speed * 12 * scale) {
6070 velocity /= velspeed;
6071 velspeed = speed * 12 * scale;
6072 velocity *= velspeed;
6074 velocity.y += gravity * multiplier * 20;
6075 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6076 velspeed = findLength(&velocity);
6077 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6080 if (animTarget == staggerbackhighanim) {
6081 coords -= facing * multiplier * speed * 16 * scale;
6084 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6085 coords -= facing * multiplier * speed * 20 * scale;
6089 if (animTarget == backhandspringanim) {
6090 //coords-=facing*multiplier*50*scale;
6091 velocity += facing * multiplier * speed * 700 * scale * -1;
6092 velspeed = findLength(&velocity);
6093 if (velspeed > speed * 50 * scale) {
6094 velocity /= velspeed;
6095 velspeed = speed * 50 * scale;
6096 velocity *= velspeed;
6098 velocity.y += gravity * multiplier * 20;
6099 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6100 velspeed = findLength(&velocity);
6101 velocity = flatfacing * velspeed * -1;
6103 if (animTarget == dodgebackanim) {
6104 //coords-=facing*multiplier*50*scale;
6105 velocity += facing * multiplier * speed * 700 * scale * -1;
6106 velspeed = findLength(&velocity);
6107 if (velspeed > speed * 60 * scale) {
6108 velocity /= velspeed;
6109 velspeed = speed * 60 * scale;
6110 velocity *= velspeed;
6112 velocity.y += gravity * multiplier * 20;
6113 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6114 velspeed = findLength(&velocity);
6115 velocity = flatfacing * velspeed * -1;
6118 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6119 velspeed = findLength(&velocity);
6122 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6123 velocity.y += gravity * multiplier;
6126 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6127 coords += velocity * multiplier;
6130 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6131 if (isFlip() && targetFrame().label == 7) {
6135 if (animTarget == jumpupanim) {
6137 animTarget = getIdle();
6144 pause_sound(whooshsound);
6145 OPENAL_SetVolume(channels[whooshsound], 0);
6148 if (animTarget == jumpdownanim || isFlip()) {
6152 animTarget = getLanding();
6153 emit_sound_at(landsound, coords, 128.);
6156 addEnvSound(coords);
6161 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6162 coords.y += gravity * multiplier * 2;
6164 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6165 coords.y = terrain.getHeight(coords.x, coords.z);
6169 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)) {
6170 velspeed = findLength(&velocity);
6172 if (velspeed < multiplier * 300 * scale) {
6175 velocity -= velocity / velspeed * multiplier * 300 * scale;
6177 if (velspeed > 5 && (isLanding() || isLandhard())) {
6178 skiddingdelay += multiplier;
6179 if (skiddelay <= 0) {
6180 FootLand(leftfoot, .5);
6181 FootLand(rightfoot, .5);
6190 velspeed = findLength(&velocity);
6192 if (velspeed > 5 && (isLanding() || isLandhard())) {
6193 skiddingdelay += multiplier;
6194 if (skiddelay <= 0) {
6195 FootLand(leftfoot, .5);
6196 FootLand(rightfoot, .5);
6204 if (skiddingdelay < 0) {
6205 skiddingdelay += multiplier;
6207 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6209 if (!onterrain || environment == grassyenvironment) {
6210 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6212 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6216 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6217 terrainnormal = victim->coords - coords;
6218 Normalise(&terrainnormal);
6219 targetyaw = -asin(0 - terrainnormal.x);
6220 targetyaw *= 360 / 6.28;
6221 if (terrainnormal.z < 0) {
6222 targetyaw = 180 - targetyaw;
6224 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6227 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6228 targetyaw = victim->targetyaw;
6230 if (animTarget == rabbittacklinganim) {
6231 coords = victim->coords;
6234 skeleton.oldfree = skeleton.free;
6238 midterrain.x = terrain.size * terrain.scale / 2;
6239 midterrain.z = terrain.size * terrain.scale / 2;
6240 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6242 tempposit = coords - midterrain;
6244 Normalise(&tempposit);
6245 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6246 coords.x = tempposit.x + midterrain.x;
6247 coords.z = tempposit.z + midterrain.z;
6252 * inverse kinematics helper function
6254 void IKHelper(Person* p, float interp)
6256 XYZ point, change, change2;
6257 float heightleft, heightright;
6259 // TODO: implement localToWorld and worldToLocal
6260 // but keep in mind it won't be the same math if player is ragdolled or something
6261 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6262 // then comb through code for places where to use it
6264 // point = localToWorld(jointPos(leftfoot))
6265 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6266 // adjust height of foot
6267 heightleft = terrain.getHeight(point.x, point.z) + .04;
6268 point.y = heightleft;
6269 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6270 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6271 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6272 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6273 // move ankle along with foot
6274 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6275 // average knee pos between old and new pos
6276 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6278 // do same as above for right leg
6279 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6280 heightright = terrain.getHeight(point.x, point.z) + .04;
6281 point.y = heightright;
6282 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6283 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6284 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6285 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6286 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6288 // fix up skeleton now that we've moved body parts?
6289 p->skeleton.DoConstraints(&p->coords, &p->scale);
6296 int Person::DrawSkeleton()
6298 int oldplayerdetail;
6299 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6300 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6310 glAlphaFunc(GL_GREATER, 0.0001);
6312 float terrainheight;
6314 if (!isnormal(yaw)) {
6317 if (!isnormal(tilt)) {
6320 if (!isnormal(tilt2)) {
6323 oldplayerdetail = playerdetail;
6325 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6328 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6331 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6337 if (playerdetail != oldplayerdetail) {
6339 normalsupdatedelay = 0;
6341 static float updatedelaychange;
6342 static float morphness;
6343 static float framemult;
6345 skeleton.FindForwards();
6346 if (howactive == typesittingwall) {
6347 skeleton.specialforward[1] = 0;
6348 skeleton.specialforward[1].z = 1;
6354 static int weaponattachmuscle;
6355 static int weaponrotatemuscle;
6356 static XYZ weaponpoint;
6357 static int start, endthing;
6358 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6359 if (!isSleeping() && !isSitting()) {
6360 // TODO: give these meaningful names
6361 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6362 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6364 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6366 if (creature == wolftype) {
6371 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6372 IKHelper(this, target);
6373 if (creature == wolftype) {
6374 IKHelper(this, target);
6378 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6379 IKHelper(this, 1 - target);
6380 if (creature == wolftype) {
6381 IKHelper(this, 1 - target);
6386 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())) {
6389 targetheadyaw = -targetyaw;
6390 targetheadpitch = 0;
6391 if (Animation::animations[animTarget].attack == 3) {
6392 targetheadyaw += 180;
6395 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6396 skeleton.drawmodel.vertex[i] = 0;
6397 skeleton.drawmodel.vertex[i].y = 999;
6399 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6400 skeleton.drawmodellow.vertex[i] = 0;
6401 skeleton.drawmodellow.vertex[i].y = 999;
6403 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6404 skeleton.drawmodelclothes.vertex[i] = 0;
6405 skeleton.drawmodelclothes.vertex[i].y = 999;
6407 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6408 // convenience renames
6409 const int p1 = skeleton.muscles[i].parent1->label;
6410 const int p2 = skeleton.muscles[i].parent2->label;
6412 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6417 if (p1 == righthand || p2 == righthand) {
6418 morphness = righthandmorphness;
6419 start = righthandmorphstart;
6420 endthing = righthandmorphend;
6422 if (p1 == lefthand || p2 == lefthand) {
6423 morphness = lefthandmorphness;
6424 start = lefthandmorphstart;
6425 endthing = lefthandmorphend;
6427 if (p1 == head || p2 == head) {
6428 morphness = headmorphness;
6429 start = headmorphstart;
6430 endthing = headmorphend;
6432 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6433 morphness = chestmorphness;
6434 start = chestmorphstart;
6435 endthing = chestmorphend;
6437 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6438 morphness = tailmorphness;
6439 start = tailmorphstart;
6440 endthing = tailmorphend;
6443 skeleton.FindRotationMuscle(i, animTarget);
6445 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6446 glMatrixMode(GL_MODELVIEW);
6449 if (!skeleton.free) {
6450 glRotatef(tilt2, 1, 0, 0);
6452 if (!skeleton.free) {
6453 glRotatef(tilt, 0, 0, 1);
6456 glTranslatef(mid.x, mid.y, mid.z);
6458 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6459 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6461 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6462 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6464 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6465 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6467 if (playerdetail || skeleton.free == 3) {
6468 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6469 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6470 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6471 glMatrixMode(GL_MODELVIEW);
6473 if (p1 == abdomen || p2 == abdomen) {
6474 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(1).x,
6475 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(1).y,
6476 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(1).z);
6478 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6479 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(2).x,
6480 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(2).y,
6481 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(2).z);
6483 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6484 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(3).x,
6485 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(3).y,
6486 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(3).z);
6488 if (p1 == head || p2 == head) {
6489 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(0).x,
6490 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(0).y,
6491 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(0).z);
6493 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6494 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6495 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6496 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6500 if (!playerdetail || skeleton.free == 3) {
6501 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6502 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6503 glMatrixMode(GL_MODELVIEW);
6505 if (p1 == abdomen || p2 == abdomen) {
6506 glTranslatef(v0.x * getProportionXYZ(1).x,
6507 v0.y * getProportionXYZ(1).y,
6508 v0.z * getProportionXYZ(1).z);
6510 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6511 glTranslatef(v0.x * getProportionXYZ(2).x,
6512 v0.y * getProportionXYZ(2).y,
6513 v0.z * getProportionXYZ(2).z);
6515 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6516 glTranslatef(v0.x * getProportionXYZ(3).x,
6517 v0.y * getProportionXYZ(3).y,
6518 v0.z * getProportionXYZ(3).z);
6520 if (p1 == head || p2 == head) {
6521 glTranslatef(v0.x * getProportionXYZ(0).x,
6522 v0.y * getProportionXYZ(0).y,
6523 v0.z * getProportionXYZ(0).z);
6526 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6527 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6528 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6529 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6535 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6536 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6538 glMatrixMode(GL_MODELVIEW);
6541 if (!skeleton.free) {
6542 glRotatef(tilt2, 1, 0, 0);
6544 if (!skeleton.free) {
6545 glRotatef(tilt, 0, 0, 1);
6547 glTranslatef(mid.x, mid.y, mid.z);
6548 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6549 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6551 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6552 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6554 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6555 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6557 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6558 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6559 glMatrixMode(GL_MODELVIEW);
6561 if (p1 == abdomen || p2 == abdomen) {
6562 glTranslatef(v0.x * getProportionXYZ(1).x,
6563 v0.y * getProportionXYZ(1).y,
6564 v0.z * getProportionXYZ(1).z);
6566 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6567 glTranslatef(v0.x * getProportionXYZ(2).x,
6568 v0.y * getProportionXYZ(2).y,
6569 v0.z * getProportionXYZ(2).z);
6571 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6572 glTranslatef(v0.x * getProportionXYZ(3).x,
6573 v0.y * getProportionXYZ(3).y,
6574 v0.z * getProportionXYZ(3).z);
6576 if (p1 == head || p2 == head) {
6577 glTranslatef(v0.x * getProportionXYZ(0).x,
6578 v0.y * getProportionXYZ(0).y,
6579 v0.z * getProportionXYZ(0).z);
6581 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6582 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6583 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6584 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6589 updatedelay = 1 + (float)(Random() % 100) / 1000;
6591 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6592 normalsupdatedelay = 1;
6593 if (playerdetail || skeleton.free == 3) {
6594 skeleton.drawmodel.CalculateNormals(0);
6596 if (!playerdetail || skeleton.free == 3) {
6597 skeleton.drawmodellow.CalculateNormals(0);
6599 if (skeleton.clothes) {
6600 skeleton.drawmodelclothes.CalculateNormals(0);
6603 if (playerdetail || skeleton.free == 3) {
6604 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6606 if (!playerdetail || skeleton.free == 3) {
6607 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6609 if (skeleton.clothes) {
6610 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6615 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6616 if (updatedelaychange > -realmultiplier * 30) {
6617 updatedelaychange = -realmultiplier * 30;
6619 if (updatedelaychange > -framemult * 4) {
6620 updatedelaychange = -framemult * 4;
6622 if (skeleton.free == 1) {
6623 updatedelaychange *= 6;
6626 updatedelaychange *= 8;
6628 updatedelay += updatedelaychange;
6630 glMatrixMode(GL_MODELVIEW);
6632 glTranslatef(coords.x, coords.y - .02, coords.z);
6633 if (!skeleton.free) {
6634 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6635 glRotatef(yaw, 0, 1, 0);
6639 glColor4f(.4, 1, .4, 1);
6640 glDisable(GL_LIGHTING);
6641 glDisable(GL_TEXTURE_2D);
6644 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6645 XYZ& v0 = skeleton.drawmodel.vertex[i];
6646 glVertex3f(v0.x, v0.y, v0.z);
6653 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6654 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6655 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6656 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6657 glVertex3f(v0.x, v0.y, v0.z);
6658 glVertex3f(v1.x, v1.y, v1.z);
6659 glVertex3f(v1.x, v1.y, v1.z);
6660 glVertex3f(v2.x, v2.y, v2.z);
6661 glVertex3f(v2.x, v2.y, v2.z);
6662 glVertex3f(v0.x, v0.y, v0.z);
6669 terrainlight = terrain.getLighting(coords.x, coords.z);
6670 distance = distsq(&viewer, &coords);
6671 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6676 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6677 if (terrainheight < 1) {
6680 if (terrainheight > 1.7) {
6681 terrainheight = 1.7;
6684 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6685 glDisable(GL_BLEND);
6686 glAlphaFunc(GL_GREATER, 0.0001);
6687 glEnable(GL_TEXTURE_2D);
6689 glDisable(GL_TEXTURE_2D);
6690 glColor4f(.7, .35, 0, .5);
6692 glEnable(GL_LIGHTING);
6695 if (Tutorial::active && id != 0) {
6696 glColor4f(.7, .7, .7, 0.6);
6698 glEnable(GL_LIGHTING);
6700 if (canattack && cananger) {
6701 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6702 glDisable(GL_TEXTURE_2D);
6703 glColor4f(1, 0, 0, 0.8);
6706 glMatrixMode(GL_TEXTURE);
6708 glTranslatef(0, -smoketex, 0);
6709 glTranslatef(-smoketex, 0, 0);
6713 if (Tutorial::active && (id != 0)) {
6714 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6716 skeleton.drawmodel.draw();
6720 if (!playerdetail) {
6721 if (Tutorial::active && (id != 0)) {
6722 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6724 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6728 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6729 if (Tutorial::active && id != 0) {
6731 glMatrixMode(GL_MODELVIEW);
6732 glEnable(GL_TEXTURE_2D);
6733 glColor4f(.7, .7, .7, 0.6);
6735 glEnable(GL_LIGHTING);
6737 if (canattack && cananger) {
6738 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6739 glDisable(GL_TEXTURE_2D);
6740 glColor4f(1, 0, 0, 0.8);
6743 glMatrixMode(GL_TEXTURE);
6745 glTranslatef(0, -smoketex * .6, 0);
6746 glTranslatef(smoketex * .6, 0, 0);
6749 if (Tutorial::active && (id != 0)) {
6750 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6752 skeleton.drawmodel.draw();
6756 if (!playerdetail) {
6757 if (Tutorial::active && (id != 0)) {
6758 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6760 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6766 if (Tutorial::active && id != 0) {
6768 glMatrixMode(GL_MODELVIEW);
6769 glEnable(GL_TEXTURE_2D);
6771 if (skeleton.clothes) {
6775 skeleton.drawmodelclothes.draw();
6778 skeleton.drawmodelclothes.drawimmediate();
6785 if (num_weapons > 0) {
6786 for (k = 0; k < num_weapons; k++) {
6787 int i = weaponids[k];
6788 if (weaponactive == k) {
6789 if (weapons[i].getType() != staff) {
6790 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6791 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6792 weaponattachmuscle = j;
6795 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6796 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) {
6797 weaponrotatemuscle = j;
6800 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6801 if (creature == wolftype) {
6802 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6805 if (weapons[i].getType() == staff) {
6806 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6807 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6808 weaponattachmuscle = j;
6811 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6812 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) {
6813 weaponrotatemuscle = j;
6816 //weaponpoint=jointPos(rightwrist);
6817 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6818 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6819 XYZ tempnormthing, vec1, vec2;
6820 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6821 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6822 CrossProduct(&vec1, &vec2, &tempnormthing);
6823 Normalise(&tempnormthing);
6824 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
6825 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6829 if (weaponactive != k && weaponstuck != k) {
6830 if (weapons[i].getType() == knife) {
6831 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6833 if (weapons[i].getType() == sword) {
6834 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6836 if (weapons[i].getType() == staff) {
6837 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6839 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6840 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) {
6841 weaponrotatemuscle = j;
6845 if (weaponstuck == k) {
6846 if (weaponstuckwhere == 0) {
6847 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6849 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6851 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6852 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) {
6853 weaponrotatemuscle = j;
6857 if (skeleton.free) {
6858 weapons[i].position = weaponpoint * scale + coords;
6859 weapons[i].bigrotation = 0;
6860 weapons[i].bigtilt = 0;
6861 weapons[i].bigtilt2 = 0;
6863 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;
6864 weapons[i].bigrotation = yaw;
6865 weapons[i].bigtilt = tilt;
6866 weapons[i].bigtilt2 = tilt2;
6868 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6869 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6870 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6871 if (weaponactive == k) {
6872 if (weapons[i].getType() == knife) {
6873 weapons[i].smallrotation = 180;
6874 weapons[i].smallrotation2 = 0;
6875 if (isCrouch() || wasCrouch()) {
6876 weapons[i].smallrotation2 = 20;
6878 if (animTarget == hurtidleanim) {
6879 weapons[i].smallrotation2 = 50;
6881 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6882 XYZ temppoint1, temppoint2;
6885 temppoint1 = jointPos(righthand);
6886 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6887 distance = findDistance(&temppoint1, &temppoint2);
6888 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6889 weapons[i].rotation2 *= 360 / 6.28;
6892 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6893 weapons[i].rotation1 *= 360 / 6.28;
6894 weapons[i].rotation3 = 0;
6895 weapons[i].smallrotation = -90;
6896 weapons[i].smallrotation2 = 0;
6897 if (temppoint1.x > temppoint2.x) {
6898 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6901 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6902 XYZ temppoint1, temppoint2;
6905 temppoint1 = jointPos(righthand);
6906 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6907 distance = findDistance(&temppoint1, &temppoint2);
6908 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6909 weapons[i].rotation2 *= 360 / 6.28;
6912 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6913 weapons[i].rotation1 *= 360 / 6.28;
6914 weapons[i].rotation3 = 0;
6915 weapons[i].smallrotation = 90;
6916 weapons[i].smallrotation2 = 0;
6917 if (temppoint1.x > temppoint2.x) {
6918 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6921 if (animTarget == knifethrowanim) {
6922 weapons[i].smallrotation = 90;
6923 //weapons[i].smallrotation2=-90;
6924 weapons[i].smallrotation2 = 0;
6925 weapons[i].rotation1 = 0;
6926 weapons[i].rotation2 = 0;
6927 weapons[i].rotation3 = 0;
6929 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6930 weapons[i].smallrotation = -90;
6931 weapons[i].rotation1 = 0;
6932 weapons[i].rotation2 = 0;
6933 weapons[i].rotation3 = 0;
6936 if (weapons[i].getType() == sword) {
6937 weapons[i].smallrotation = 0;
6938 weapons[i].smallrotation2 = 0;
6939 if (animTarget == knifethrowanim) {
6940 weapons[i].smallrotation = -90;
6941 weapons[i].smallrotation2 = 0;
6942 weapons[i].rotation1 = 0;
6943 weapons[i].rotation2 = 0;
6944 weapons[i].rotation3 = 0;
6946 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)) {
6947 XYZ temppoint1, temppoint2;
6950 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6951 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6952 distance = findDistance(&temppoint1, &temppoint2);
6953 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6954 weapons[i].rotation2 *= 360 / 6.28;
6957 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6958 weapons[i].rotation1 *= 360 / 6.28;
6959 weapons[i].rotation3 = 0;
6960 weapons[i].smallrotation = 90;
6961 weapons[i].smallrotation2 = 0;
6962 if (temppoint1.x > temppoint2.x) {
6963 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6967 if (weapons[i].getType() == staff) {
6968 weapons[i].smallrotation = 100;
6969 weapons[i].smallrotation2 = 0;
6970 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6971 XYZ temppoint1, temppoint2;
6974 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6975 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6976 distance = findDistance(&temppoint1, &temppoint2);
6977 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6978 weapons[i].rotation2 *= 360 / 6.28;
6981 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6982 weapons[i].rotation1 *= 360 / 6.28;
6983 weapons[i].rotation3 = 0;
6984 weapons[i].smallrotation = 90;
6985 weapons[i].smallrotation2 = 0;
6986 if (temppoint1.x > temppoint2.x) {
6987 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6992 if (weaponactive != k && weaponstuck != k) {
6993 if (weapons[i].getType() == knife) {
6994 weapons[i].smallrotation = -70;
6995 weapons[i].smallrotation2 = 10;
6997 if (weapons[i].getType() == sword) {
6998 weapons[i].smallrotation = -100;
6999 weapons[i].smallrotation2 = -8;
7001 if (weapons[i].getType() == staff) {
7002 weapons[i].smallrotation = -100;
7003 weapons[i].smallrotation2 = -8;
7006 if (weaponstuck == k) {
7007 if (weaponstuckwhere == 0) {
7008 weapons[i].smallrotation = 180;
7010 weapons[i].smallrotation = 0;
7012 weapons[i].smallrotation2 = 10;
7019 if (skeleton.free) {
7022 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7025 if (animCurrent != animTarget) {
7028 if (skeleton.free == 2) {
7037 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7039 static float distance;
7040 static float olddistance;
7041 static int intersecting;
7042 static int firstintersecting;
7045 static XYZ start, end;
7046 static float slopethreshold = -.4;
7048 firstintersecting = -1;
7052 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7056 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7058 for (int i = 0; i < 4; i++) {
7059 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7060 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7062 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)));
7063 if (distance < radius) {
7064 point = *p1 - model->Triangles[j].facenormal * distance;
7065 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]])) {
7068 if (!intersecting) {
7069 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7070 &model->vertex[model->Triangles[j].vertex[1]],
7073 if (!intersecting) {
7074 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7075 &model->vertex[model->Triangles[j].vertex[2]],
7078 if (!intersecting) {
7079 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7080 &model->vertex[model->Triangles[j].vertex[2]],
7084 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7088 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)) {
7089 p1->y = point.y + radius;
7090 if ((animTarget == jumpdownanim || isFlip())) {
7091 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7095 if (animTarget == jumpupanim) {
7097 animTarget = getIdle();
7104 pause_sound(whooshsound);
7105 OPENAL_SetVolume(channels[whooshsound], 0);
7108 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7112 animTarget = getLanding();
7113 emit_sound_at(landsound, coords, 128.);
7116 addEnvSound(coords);
7123 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7124 olddistance = distance;
7125 firstintersecting = j;
7130 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7131 if (model->Triangles[j].facenormal.y > slopethreshold) {
7134 start.y -= radius / 4;
7135 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7136 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7137 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7138 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)));
7139 if (distance < radius * .5) {
7140 point = start - model->Triangles[j].facenormal * distance;
7141 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7144 if (!intersecting) {
7145 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7147 if (!intersecting) {
7148 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7150 if (!intersecting) {
7151 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7154 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7155 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7157 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;
7158 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7162 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7165 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7166 olddistance = distance;
7167 firstintersecting = j;
7174 *p = DoRotation(*p, 0, *rotate, 0);
7178 *p1 = DoRotation(*p1, 0, *rotate, 0);
7181 return firstintersecting;
7184 int findPathDist(int start, int end)
7189 unsigned int smallestcount = 1000;
7190 for (char i = 0; i < 50; i++) {
7191 unsigned int count = 0;
7196 while (last != end && count < 30) {
7198 for (int j = 0; j < Game::numpathpoints; j++) {
7199 if (j != last && j != last2 && j != last3 && j != last4) {
7201 if (Game::numpathpointconnect[j]) {
7202 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7203 if (Game::pathpointconnect[j][k] == last) {
7209 if (Game::numpathpointconnect[last]) {
7210 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7211 if (Game::pathpointconnect[last][k] == j) {
7218 if (closest == -1 || Random() % 2 == 0) {
7230 if (count < smallestcount) {
7231 smallestcount = count;
7234 return smallestcount;
7237 void Person::takeWeapon(int weaponId)
7240 weapons[weaponId].owner = id;
7241 if (num_weapons > 0) {
7242 weaponids[num_weapons] = weaponids[0];
7245 weaponids[0] = weaponId;
7248 void Person::addClothes()
7250 if (numclothes > 0) {
7251 for (int i = 0; i < numclothes; i++) {
7258 bool Person::addClothes(const int& clothesId)
7261 const std::string fileName = clothes[clothesId];
7263 GLubyte* array = &skeleton.skinText[0];
7267 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7272 float tintr = clothestintr[clothesId];
7273 float tintg = clothestintg[clothesId];
7274 float tintb = clothestintb[clothesId];
7296 int bytesPerPixel = texture.bpp / 8;
7300 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7301 if (bytesPerPixel == 3) {
7303 } else if ((i + 1) % 4 == 0) {
7304 alphanum = texture.data[i];
7306 if ((i + 1) % 4 || bytesPerPixel == 3) {
7308 texture.data[i] *= tintr;
7311 texture.data[i] *= tintg;
7314 texture.data[i] *= tintb;
7316 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7328 if (!isPlayerControlled() && !Dialog::inDialog()) {
7330 //disable movement in editor
7331 if (Game::editorenabled) {
7336 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7337 Person::players[0]->coords.y > coords.y + 2 &&
7338 !Person::players[0]->onterrain) {
7343 if (aitype == pathfindtype) {
7344 if (finalpathfindpoint == -1) {
7345 float closestdistance;
7346 float tempdist = 0.0f;
7350 closestdistance = -1;
7351 for (int j = 0; j < Game::numpathpoints; j++) {
7352 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7353 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7355 finaltarget = Game::pathpoint[j];
7358 finalpathfindpoint = closest;
7359 for (int j = 0; j < Game::numpathpoints; j++) {
7360 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7361 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7362 if (sq(tempdist) < closestdistance) {
7363 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7364 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7365 closestdistance = sq(tempdist);
7367 finaltarget = colpoint;
7372 finalpathfindpoint = closest;
7374 if (targetpathfindpoint == -1) {
7375 float closestdistance;
7376 float tempdist = 0.0f;
7380 closestdistance = -1;
7381 if (lastpathfindpoint == -1) {
7382 for (int j = 0; j < Game::numpathpoints; j++) {
7383 if (j != lastpathfindpoint) {
7384 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7385 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7390 targetpathfindpoint = closest;
7391 for (int j = 0; j < Game::numpathpoints; j++) {
7392 if (j != lastpathfindpoint) {
7393 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7394 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7395 if (sq(tempdist) < closestdistance) {
7396 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7397 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7398 closestdistance = sq(tempdist);
7405 targetpathfindpoint = closest;
7407 for (int j = 0; j < Game::numpathpoints; j++) {
7408 if (j != lastpathfindpoint &&
7409 j != lastpathfindpoint2 &&
7410 j != lastpathfindpoint3 &&
7411 j != lastpathfindpoint4) {
7413 if (Game::numpathpointconnect[j]) {
7414 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7415 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7421 if (Game::numpathpointconnect[lastpathfindpoint]) {
7422 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7423 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7430 tempdist = findPathDist(j, finalpathfindpoint);
7431 if (closest == -1 || tempdist < closestdistance) {
7432 closestdistance = tempdist;
7438 targetpathfindpoint = closest;
7441 losupdatedelay -= multiplier;
7443 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7444 lookyaw = targetyaw;
7446 //reached target point
7447 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7448 lastpathfindpoint4 = lastpathfindpoint3;
7449 lastpathfindpoint3 = lastpathfindpoint2;
7450 lastpathfindpoint2 = lastpathfindpoint;
7451 lastpathfindpoint = targetpathfindpoint;
7452 if (lastpathfindpoint2 == -1) {
7453 lastpathfindpoint2 = lastpathfindpoint;
7455 if (lastpathfindpoint3 == -1) {
7456 lastpathfindpoint3 = lastpathfindpoint2;
7458 if (lastpathfindpoint4 == -1) {
7459 lastpathfindpoint4 = lastpathfindpoint3;
7461 targetpathfindpoint = -1;
7463 if (distsqflat(&coords, &finalfinaltarget) <
7464 distsqflat(&coords, &finaltarget) ||
7465 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7466 lastpathfindpoint == finalpathfindpoint) {
7467 aitype = passivetype;
7478 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7479 targetyaw += 90 * (whichdirection * 2 - 1);
7482 if (collided < 1 || animTarget != jumpupanim) {
7485 if ((collided > .8 && jumppower >= 5)) {
7489 if ((!Tutorial::active || cananger) &&
7491 !isPlayerFriend() &&
7492 !Person::players[0]->dead &&
7493 distsq(&coords, &Person::players[0]->coords) < 400 &&
7495 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7496 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7497 !Game::editorenabled &&
7498 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7499 aitype = attacktypecutoff;
7501 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7502 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7503 !Game::editorenabled) {
7504 aitype = attacktypecutoff;
7507 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7508 losupdatedelay = .2;
7509 for (unsigned j = 0; j < Person::players.size(); j++) {
7510 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7511 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7512 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7513 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7514 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7515 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) ||
7516 (Person::players[j]->animTarget == hanganim &&
7517 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7518 aitype = searchtype;
7520 lastseen = Person::players[j]->coords;
7531 if (aitype == attacktypecutoff && Game::musictype != 2) {
7532 if (creature != wolftype) {
7539 if (aitype != passivetype && Game::leveltime > .5) {
7540 howactive = typeactive;
7543 if (aitype == passivetype) {
7544 aiupdatedelay -= multiplier;
7545 losupdatedelay -= multiplier;
7546 lastseentime += multiplier;
7547 pausetime -= multiplier;
7548 if (lastseentime > 1) {
7552 if (aiupdatedelay < 0) {
7553 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7554 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7555 lookyaw = targetyaw;
7556 aiupdatedelay = .05;
7558 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7559 if (waypointtype[waypoint] == wppause) {
7563 if (waypoint > numwaypoints - 1) {
7569 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7581 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7582 if (!avoidsomething) {
7583 targetyaw += 90 * (whichdirection * 2 - 1);
7585 XYZ leftpos, rightpos;
7586 float leftdist, rightdist;
7587 leftpos = coords + DoRotation(facing, 0, 90, 0);
7588 rightpos = coords - DoRotation(facing, 0, 90, 0);
7589 leftdist = distsq(&leftpos, &avoidwhere);
7590 rightdist = distsq(&rightpos, &avoidwhere);
7591 if (leftdist < rightdist) {
7599 if (collided < 1 || animTarget != jumpupanim) {
7602 if ((collided > .8 && jumppower >= 5)) {
7607 if (!Game::editorenabled) {
7608 if (howactive <= typesleeping) {
7609 if (numenvsounds > 0 && (!Tutorial::active || cananger) && !isPlayerFriend() && hostile) {
7610 for (int j = 0; j < numenvsounds; j++) {
7611 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7612 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7613 aitype = attacktypecutoff;
7619 if (aitype != passivetype) {
7620 if (howactive == typesleeping) {
7621 setTargetAnimation(getupfromfrontanim);
7623 howactive = typeactive;
7627 if (howactive < typesleeping &&
7628 ((!Tutorial::active || cananger) && hostile) &&
7629 !isPlayerFriend() &&
7630 !Person::players[0]->dead &&
7631 distsq(&coords, &Person::players[0]->coords) < 400 &&
7633 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7634 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7635 aitype = attacktypecutoff;
7637 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7638 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7639 aitype = attacktypecutoff;
7643 if (creature == wolftype) {
7645 for (unsigned j = 0; j < Person::players.size(); j++) {
7646 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7647 float smelldistance = 50;
7648 if (j == 0 && Person::players[j]->num_weapons > 0) {
7649 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7650 smelldistance = 100;
7652 if (Person::players[j]->num_weapons == 2) {
7653 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7654 smelldistance = 100;
7659 smelldistance = 100;
7661 windsmell = windvector;
7662 Normalise(&windsmell);
7663 windsmell = windsmell * 2 + Person::players[j]->coords;
7664 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7665 aitype = attacktypecutoff;
7671 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7672 losupdatedelay = .2;
7673 for (unsigned j = 0; j < Person::players.size(); j++) {
7674 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7675 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7676 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7677 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7678 if ((-1 == Object::checkcollide(
7679 DoRotation(jointPos(head), 0, yaw, 0) *
7682 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7683 Person::players[j]->scale +
7684 Person::players[j]->coords) &&
7685 !Person::players[j]->isWallJump()) ||
7686 (Person::players[j]->animTarget == hanganim &&
7687 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7689 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7698 if (lastseentime <= 0) {
7699 aitype = searchtype;
7701 lastseen = Person::players[j]->coords;
7709 if (aitype == attacktypecutoff && Game::musictype != 2) {
7710 if (creature != wolftype) {
7714 if (creature == wolftype) {
7724 if (aitype == searchtype) {
7725 aiupdatedelay -= multiplier;
7726 losupdatedelay -= multiplier;
7728 lastseentime -= multiplier;
7730 lastchecktime -= multiplier;
7732 if (isRun() && !onground) {
7733 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7734 XYZ test2 = coords + facing;
7736 XYZ test = coords + facing;
7738 j = Object::checkcollide(test2, test, laststanding);
7740 j = Object::checkcollide(test2, test);
7744 setTargetAnimation(getStop());
7747 //aitype=passivetype;
7748 aitype = pathfindtype;
7749 finalfinaltarget = waypoints[waypoint];
7750 finalpathfindpoint = -1;
7751 targetpathfindpoint = -1;
7752 lastpathfindpoint = -1;
7753 lastpathfindpoint2 = -1;
7754 lastpathfindpoint3 = -1;
7755 lastpathfindpoint4 = -1;
7761 //check out last seen location
7762 if (aiupdatedelay < 0) {
7763 targetyaw = roughDirectionTo(coords, lastseen);
7764 lookyaw = targetyaw;
7765 aiupdatedelay = .05;
7768 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7771 lastseen.x += (float(Random() % 100) - 50) / 25;
7772 lastseen.z += (float(Random() % 100) - 50) / 25;
7783 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7784 if (!avoidsomething) {
7785 targetyaw += 90 * (whichdirection * 2 - 1);
7787 XYZ leftpos, rightpos;
7788 float leftdist, rightdist;
7789 leftpos = coords + DoRotation(facing, 0, 90, 0);
7790 rightpos = coords - DoRotation(facing, 0, 90, 0);
7791 leftdist = distsq(&leftpos, &avoidwhere);
7792 rightdist = distsq(&rightpos, &avoidwhere);
7793 if (leftdist < rightdist) {
7801 if (collided < 1 || animTarget != jumpupanim) {
7804 if ((collided > .8 && jumppower >= 5)) {
7808 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && !isPlayerFriend() && hostile)) {
7809 for (int k = 0; k < numenvsounds; k++) {
7810 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7811 aitype = attacktypecutoff;
7816 if (!Person::players[0]->dead &&
7817 !isPlayerFriend() &&
7818 losupdatedelay < 0 &&
7819 !Game::editorenabled &&
7821 ((!Tutorial::active || cananger) && hostile)) {
7822 losupdatedelay = .2;
7823 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7824 aitype = attacktypecutoff;
7827 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
7828 //TODO: factor out canSeePlayer()
7829 if (distsq(&coords, &Person::players[0]->coords) < 400) {
7830 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
7831 if ((Object::checkcollide(
7832 DoRotation(jointPos(head), 0, yaw, 0) *
7835 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7836 Person::players[0]->scale +
7837 Person::players[0]->coords) == -1) ||
7838 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7839 /* //TODO: changed j to 0 on a whim, make sure this is correct
7840 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7841 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7843 aitype = attacktypecutoff;
7851 if (lastseentime < 0) {
7852 //aitype=passivetype;
7854 aitype = pathfindtype;
7855 finalfinaltarget = waypoints[waypoint];
7856 finalpathfindpoint = -1;
7857 targetpathfindpoint = -1;
7858 lastpathfindpoint = -1;
7859 lastpathfindpoint2 = -1;
7860 lastpathfindpoint3 = -1;
7861 lastpathfindpoint4 = -1;
7865 if (aitype != gethelptype) {
7869 //get help from buddies
7870 if (aitype == gethelptype) {
7871 runninghowlong += multiplier;
7872 aiupdatedelay -= multiplier;
7874 if (aiupdatedelay < 0 || ally == 0) {
7878 //TODO: factor out closest search somehow
7881 float closestdist = -1;
7882 for (unsigned k = 0; k < Person::players.size(); k++) {
7883 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7884 (Person::players[k]->howactive < typedead1) &&
7885 !Person::players[k]->skeleton.free &&
7886 (Person::players[k]->aitype == passivetype)) {
7887 float distance = distsq(&coords, &Person::players[k]->coords);
7888 if (closestdist == -1 || distance < closestdist) {
7889 closestdist = distance;
7894 if (closest != -1) {
7899 lastseen = Person::players[0]->coords;
7905 XYZ facing = coords;
7906 XYZ flatfacing = Person::players[ally]->coords;
7907 facing.y += jointPos(head).y * scale;
7908 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7909 if (-1 != Object::checkcollide(facing, flatfacing)) {
7913 //no available ally, run back to player
7915 Person::players[ally]->skeleton.free ||
7916 Person::players[ally]->aitype != passivetype ||
7917 lastseentime <= 0) {
7918 aitype = searchtype;
7924 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7925 lookyaw = targetyaw;
7926 aiupdatedelay = .05;
7929 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7930 aitype = searchtype;
7932 Person::players[ally]->aitype = searchtype;
7933 if (Person::players[ally]->lastseentime < lastseentime) {
7934 Person::players[ally]->lastseen = lastseen;
7935 Person::players[ally]->lastseentime = lastseentime;
7936 Person::players[ally]->lastchecktime = lastchecktime;
7940 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7941 if (!avoidsomething) {
7942 targetyaw += 90 * (whichdirection * 2 - 1);
7944 XYZ leftpos, rightpos;
7945 float leftdist, rightdist;
7946 leftpos = coords + DoRotation(facing, 0, 90, 0);
7947 rightpos = coords - DoRotation(facing, 0, 90, 0);
7948 leftdist = distsq(&leftpos, &avoidwhere);
7949 rightdist = distsq(&rightpos, &avoidwhere);
7950 if (leftdist < rightdist) {
7965 if (collided < 1 || animTarget != jumpupanim) {
7968 if (collided > .8 && jumppower >= 5) {
7973 //retreiving a weapon on the ground
7974 if (aitype == getweapontype) {
7975 aiupdatedelay -= multiplier;
7976 lastchecktime -= multiplier;
7978 if (aiupdatedelay < 0) {
7984 float closestdist = -1;
7985 for (unsigned k = 0; k < weapons.size(); k++) {
7986 if (weapons[k].owner == -1) {
7987 float distance = distsq(&coords, &weapons[k].position);
7988 if (closestdist == -1 || distance < closestdist) {
7989 closestdist = distance;
7994 if (closest != -1) {
8003 if (!Person::players[0]->dead && !isPlayerFriend() && ((!Tutorial::active || cananger) && hostile)) {
8004 if (ally < 0 || hasWeapon() || lastchecktime <= 0) {
8005 aitype = attacktypecutoff;
8009 if (!Person::players[0]->dead) {
8011 if (weapons[ally].owner != -1 ||
8012 distsq(&coords, &weapons[ally].position) > 16) {
8013 aitype = attacktypecutoff;
8016 //TODO: factor these out as moveToward()
8017 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8018 lookyaw = targetyaw;
8019 aiupdatedelay = .05;
8022 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8023 if (!avoidsomething) {
8024 targetyaw += 90 * (whichdirection * 2 - 1);
8026 XYZ leftpos, rightpos;
8027 float leftdist, rightdist;
8028 leftpos = coords + DoRotation(facing, 0, 90, 0);
8029 rightpos = coords - DoRotation(facing, 0, 90, 0);
8030 leftdist = distsq(&leftpos, &avoidwhere);
8031 rightdist = distsq(&rightpos, &avoidwhere);
8032 if (leftdist < rightdist) {
8048 if (animTarget != crouchremoveknifeanim &&
8049 animTarget != removeknifeanim) {
8050 throwtogglekeydown = 0;
8054 if (collided < 1 || animTarget != jumpupanim) {
8057 if ((collided > .8 && jumppower >= 5)) {
8062 if (aitype == attacktypecutoff) {
8063 aiupdatedelay -= multiplier;
8064 //dodge or reverse rabbit kicks, knife throws, flips
8065 if (damage < damagetolerance * 2 / 3) {
8066 if ((Person::players[0]->animTarget == rabbitkickanim ||
8067 Person::players[0]->animTarget == knifethrowanim ||
8068 (Person::players[0]->isFlip() &&
8069 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8070 !Person::players[0]->skeleton.free &&
8071 (aiupdatedelay < .1)) {
8076 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->hasWeapon()) {
8077 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8078 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8079 if (abs(Random() % 2) == 0) {
8080 setTargetAnimation(backhandspringanim);
8082 setTargetAnimation(rollanim);
8084 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8087 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8088 setTargetAnimation(flipanim);
8093 aiupdatedelay = .02;
8096 //get confused by flips
8097 if (Person::players[0]->isFlip() &&
8098 !Person::players[0]->skeleton.free &&
8099 Person::players[0]->animTarget != walljumprightkickanim &&
8100 Person::players[0]->animTarget != walljumpleftkickanim) {
8101 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8102 if ((1 - damage / damagetolerance) > .5) {
8107 //go for weapon on the ground
8108 if (wentforweapon < 3) {
8109 for (unsigned k = 0; k < weapons.size(); k++) {
8110 if (creature != wolftype) {
8111 if (num_weapons == 0 &&
8112 weapons[k].owner == -1 &&
8113 weapons[k].velocity.x == 0 &&
8114 weapons[k].velocity.z == 0 &&
8115 weapons[k].velocity.y == 0) {
8116 if (distsq(&coords, &weapons[k].position) < 16) {
8119 aitype = getweapontype;
8126 //dodge/reverse walljump kicks
8127 if (damage < damagetolerance / 2) {
8128 if (Animation::animations[animTarget].height != highheight) {
8129 if (damage < damagetolerance * .5 &&
8130 ((Person::players[0]->animTarget == walljumprightkickanim ||
8131 Person::players[0]->animTarget == walljumpleftkickanim) &&
8132 ((aiupdatedelay < .15 &&
8134 (aiupdatedelay < .08 &&
8135 difficulty != 2)))) {
8140 //walked off a ledge (?)
8141 if (isRun() && !onground) {
8142 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8143 XYZ test2 = coords + facing;
8145 XYZ test = coords + facing;
8147 j = Object::checkcollide(test2, test, laststanding);
8149 j = Object::checkcollide(test2, test);
8153 setTargetAnimation(getStop());
8156 aitype = pathfindtype;
8157 finalfinaltarget = waypoints[waypoint];
8158 finalpathfindpoint = -1;
8159 targetpathfindpoint = -1;
8160 lastpathfindpoint = -1;
8161 lastpathfindpoint2 = -1;
8162 lastpathfindpoint3 = -1;
8163 lastpathfindpoint4 = -1;
8169 //lose sight of player in the air (?)
8170 if (Person::players[0]->coords.y > coords.y + 5 &&
8171 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8172 !Person::players[0]->onterrain) {
8173 aitype = pathfindtype;
8174 finalfinaltarget = waypoints[waypoint];
8175 finalpathfindpoint = -1;
8176 targetpathfindpoint = -1;
8177 lastpathfindpoint = -1;
8178 lastpathfindpoint2 = -1;
8179 lastpathfindpoint3 = -1;
8180 lastpathfindpoint4 = -1;
8182 //it's time to think (?)
8183 if (aiupdatedelay < 0 &&
8184 !Animation::animations[animTarget].attack &&
8185 animTarget != staggerbackhighanim &&
8186 animTarget != staggerbackhardanim &&
8187 animTarget != backhandspringanim &&
8188 animTarget != dodgebackanim) {
8190 if (!hasWeapon() && num_weapons > 0) {
8191 drawkeydown = Random() % 2;
8195 rabbitkickenabled = Random() % 2;
8197 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8198 XYZ targetpoint = Person::players[0]->coords;
8199 float vellength = findLength(&velocity);
8200 if (vellength != 0 &&
8201 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8202 targetpoint += Person::players[0]->velocity *
8203 findDistance(&Person::players[0]->coords, &coords) / vellength;
8205 targetyaw = roughDirectionTo(coords, targetpoint);
8206 lookyaw = targetyaw;
8207 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8209 if (distsq(&coords, &Person::players[0]->coords) > 5 && (!Person::players[0]->hasWeapon() || hasWeapon())) {
8211 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8212 distsq(&coords, &Person::players[0]->coords) < 9) &&
8213 Person::players[0]->hasWeapon()) {
8215 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8220 //chill out around the corpse
8221 if (Person::players[0]->dead) {
8223 if (Random() % 10 == 0) {
8226 if (Random() % 100 == 0) {
8227 aitype = pathfindtype;
8228 finalfinaltarget = waypoints[waypoint];
8229 finalpathfindpoint = -1;
8230 targetpathfindpoint = -1;
8231 lastpathfindpoint = -1;
8232 lastpathfindpoint2 = -1;
8233 lastpathfindpoint3 = -1;
8234 lastpathfindpoint4 = -1;
8243 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8244 targetyaw += 90 * (whichdirection * 2 - 1);
8247 if (Random() % 2 == 0 || hasWeapon() || creature == wolftype) {
8252 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8257 if (!isPlayerControlled() &&
8262 for (unsigned j = 0; j < Person::players.size(); j++) {
8263 if (j != id && !Person::players[j]->skeleton.free &&
8264 Person::players[j]->hasvictim &&
8265 (Tutorial::active && reversaltrain ||
8266 Random() % 2 == 0 && difficulty == 2 ||
8267 Random() % 4 == 0 && difficulty == 1 ||
8268 Random() % 8 == 0 && difficulty == 0 ||
8269 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8270 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8271 (Random() % 2 == 0 || difficulty == 2) ||
8272 (isIdle() || isRun()) &&
8273 Person::players[j]->hasWeapon() ||
8274 Person::players[j]->animTarget == swordslashanim &&
8276 Person::players[j]->animTarget == staffhitanim ||
8277 Person::players[j]->animTarget == staffspinhitanim)) {
8278 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8279 Person::players[j]->victim == Person::players[id] &&
8280 (Person::players[j]->animTarget == sweepanim ||
8281 Person::players[j]->animTarget == spinkickanim ||
8282 Person::players[j]->animTarget == staffhitanim ||
8283 Person::players[j]->animTarget == staffspinhitanim ||
8284 Person::players[j]->animTarget == winduppunchanim ||
8285 Person::players[j]->animTarget == upunchanim ||
8286 Person::players[j]->animTarget == wolfslapanim ||
8287 Person::players[j]->animTarget == knifeslashstartanim ||
8288 Person::players[j]->animTarget == swordslashanim &&
8289 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8300 Person::players[target]->Reverse();
8307 if (collided > .8 && jumppower >= 5 ||
8308 distsq(&coords, &Person::players[0]->coords) > 400 &&
8310 creature == rabbittype) {
8313 //TODO: why are we controlling the human?
8314 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8315 Person::players[0]->jumpkeydown = 0;
8317 if (Person::players[0]->animTarget == jumpdownanim &&
8318 distsq(&Person::players[0]->coords, &coords) < 40) {
8325 if (Tutorial::active) {
8331 XYZ facing = coords;
8332 XYZ flatfacing = Person::players[0]->coords;
8333 facing.y += jointPos(head).y * scale;
8334 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8335 if (occluded >= 2) {
8336 if (-1 != Object::checkcollide(facing, flatfacing)) {
8340 if (lastseentime <= 0 &&
8341 (creature != wolftype ||
8342 weaponstuck == -1)) {
8343 aitype = searchtype;
8345 lastseen = Person::players[0]->coords;
8354 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8355 (aitype == attacktypecutoff ||
8356 aitype == searchtype)) {
8357 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8358 XYZ test = Person::players[0]->coords;
8360 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8367 if (aitype == passivetype && !(numwaypoints > 1) ||
8369 pause && damage > superpermanentdamage) {
8384 // friends follow player
8387 !Person::players[0]->dead &&
8388 distsq(&coords, &Person::players[0]->coords) > 5) {
8389 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8390 XYZ targetpoint = Person::players[0]->coords;
8391 velocity = (targetpoint - coords);
8393 float vellength = findLength(&velocity);
8394 if (vellength != 0 &&
8395 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8396 targetpoint += Person::players[0]->velocity *
8397 findDistance(&Person::players[0]->coords, &coords) / vellength;
8399 targetyaw = roughDirectionTo(coords, targetpoint);
8400 lookyaw = targetyaw;
8402 aitype = searchtype;
8409 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8410 facing = flatfacing;
8412 if (aitype == attacktypecutoff) {
8413 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8414 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8415 } else if (howactive >= typesleeping) {
8416 targetheadyaw = targetyaw;
8417 targetheadpitch = 0;
8418 } else if (isPlayerFriend()) {
8419 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8420 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8422 if (interestdelay <= 0) {
8423 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8424 headtarget = coords;
8425 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8426 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8427 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8428 headtarget += facing * 1.5;
8430 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8431 targetheadpitch = pitchTo(coords, headtarget);
8436 bool Person::catchKnife()
8439 ((PersonType::types[creature].knifeCatchingType == 0) && (Random() % 2 != 0) && (!hasWeapon()) && (aitype == attacktypecutoff)) ||
8440 ((PersonType::types[creature].knifeCatchingType == 1) && (Random() % 3 != 0) && (!hasWeapon()) && (isIdle() || isRun() || animTarget == walkanim));