2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - 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/openal_wrapper.hpp"
25 #include "Audio/Sounds.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Utils/Folders.hpp"
30 #include "Tutorial.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 GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
54 extern bool decalstoggle;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern float smoketex;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern bool gamestarted;
70 extern XYZ envsound[30];
71 extern float envsoundvol[30];
72 extern int numenvsounds;
73 extern float envsoundlife[30];
75 extern XYZ windvector;
77 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
82 animCurrent(bounceidleanim),
83 animTarget(bounceidleanim),
90 howactive(typeactive),
92 superruntoggle(false),
93 lastattack(0), lastattack2(0), lastattack3(0),
94 currentoffset(), targetoffset(), offset(),
126 rabbitkickenabled(false),
135 damagetolerance(200),
138 superpermanentdamage(0),
152 bleedx(0), bleedy(0),
156 headyaw(0), headpitch(0),
157 targetheadyaw(0), targetheadpitch(0),
168 normalsupdatedelay(0),
171 forwardkeydown(false),
172 forwardstogglekeydown(false),
177 jumptogglekeydown(false),
178 crouchkeydown(false),
179 crouchtogglekeydown(false),
181 drawtogglekeydown(false),
183 throwtogglekeydown(false),
184 attackkeydown(false),
189 crouchkeydowntime(0),
203 whichdirection(false),
204 whichdirectiondelay(0),
205 avoidsomething(false),
214 lefthandmorphness(0),
215 righthandmorphness(0),
219 targetlefthandmorphness(0),
220 targetrighthandmorphness(0),
221 targetheadmorphness(1),
222 targetchestmorphness(0),
223 targettailmorphness(0),
224 lefthandmorphstart(0), lefthandmorphend(0),
225 righthandmorphstart(0), righthandmorphend(0),
226 headmorphstart(0), headmorphend(0),
227 chestmorphstart(0), chestmorphend(0),
228 tailmorphstart(0), tailmorphend(0),
231 highreversaldelay(0),
234 creature(rabbittype),
281 finalpathfindpoint(0),
282 targetpathfindpoint(0),
283 lastpathfindpoint(0),
284 lastpathfindpoint2(0),
285 lastpathfindpoint3(0),
286 lastpathfindpoint4(0),
303 neckspurtparticledelay(0),
307 rabbitkickragdoll(false),
315 /* Read a person in tfile. Throws an error if it’s not valid */
316 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
319 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
321 funpackf(tfile, "Bi", &howactive);
323 howactive = typeactive;
326 funpackf(tfile, "Bf", &scale);
331 funpackf(tfile, "Bb", &immobile);
336 funpackf(tfile, "Bf", &yaw);
341 if (num_weapons < 0 || num_weapons > 5) {
342 throw InvalidPersonException();
344 if (num_weapons > 0 && num_weapons < 5) {
345 for (int j = 0; j < num_weapons; j++) {
346 weaponids[j] = weapons.size();
348 funpackf(tfile, "Bi", &type);
349 weapons.push_back(Weapon(type, id));
352 funpackf(tfile, "Bi", &numwaypoints);
353 for (int j = 0; j < numwaypoints; j++) {
354 funpackf(tfile, "Bf", &waypoints[j].x);
355 funpackf(tfile, "Bf", &waypoints[j].y);
356 funpackf(tfile, "Bf", &waypoints[j].z);
358 funpackf(tfile, "Bi", &waypointtype[j]);
360 waypointtype[j] = wpkeepwalking;
364 funpackf(tfile, "Bi", &waypoint);
365 if (waypoint > (numwaypoints - 1)) {
369 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
370 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
371 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
372 funpackf(tfile, "Bf Bf", &power, &speedmult);
374 float headprop, legprop, armprop, bodyprop;
377 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
385 if (creature == wolftype) {
386 proportionhead = 1.1 * headprop;
387 proportionbody = 1.1 * bodyprop;
388 proportionarms = 1.1 * armprop;
389 proportionlegs = 1.1 * legprop;
390 } else if (creature == rabbittype) {
391 proportionhead = 1.2 * headprop;
392 proportionbody = 1.05 * bodyprop;
393 proportionarms = 1.00 * armprop;
394 proportionlegs = 1.1 * legprop;
395 proportionlegs.y = 1.05 * legprop;
398 funpackf(tfile, "Bi", &numclothes);
399 for (int k = 0; k < numclothes; k++) {
401 funpackf(tfile, "Bi", &templength);
402 for (int l = 0; l < templength; l++)
403 funpackf(tfile, "Bb", &clothes[k][l]);
404 clothes[k][templength] = '\0';
405 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
411 if (creature == wolftype) {
413 damagetolerance = 300;
420 realoldcoords = coords;
423 void Person::skeletonLoad(bool clothes)
426 if (creature != wolftype) {
428 "Skeleton/BasicFigure",
429 "Skeleton/BasicFigureLow",
430 "Skeleton/RabbitBelt",
432 "Models/Body2.solid",
433 "Models/Body3.solid",
434 "Models/Body4.solid",
435 "Models/Body5.solid",
436 "Models/Body6.solid",
437 "Models/Body7.solid",
438 "Models/BodyLow.solid",
444 "Skeleton/BasicFigureWolf",
445 "Skeleton/BasicFigureWolfLow",
446 "Skeleton/RabbitBelt",
448 "Models/Wolf2.solid",
449 "Models/Wolf3.solid",
450 "Models/Wolf4.solid",
451 "Models/Wolf5.solid",
452 "Models/Wolf6.solid",
453 "Models/Wolf7.solid",
454 "Models/WolfLow.solid",
460 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
466 * GameTick/doPlayerCollisions
468 void Person::CheckKick()
471 && (animTarget == rabbitkickanim
473 && victim != this->shared_from_this()
475 && animCurrent == rabbitkickanim)
476 && distsq(&coords, &victim->coords) < 1.2
477 && !victim->skeleton.free))
480 if (Animation::animations[victim->animTarget].height != lowheight) {
481 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
482 XYZ relative = velocity;
484 Normalise(&relative);
488 if (!Tutorial::active)
489 emit_sound_at(heavyimpactsound, victim->coords);
491 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
492 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
495 victim->DoDamage(100 * damagemult / victim->protectionhigh);
501 animTarget = backflipanim;
503 velocity = facing * -10;
507 resume_stream(whooshsound);
509 award_bonus(id, cannon);
510 } else if (victim->isCrouch()) {
511 animTarget = rabbitkickreversedanim;
512 animCurrent = rabbitkickreversedanim;
513 victim->animCurrent = rabbitkickreversalanim;
514 victim->animTarget = rabbitkickreversalanim;
520 victim->oldcoords = victim->coords;
521 coords = victim->coords;
522 victim->targetyaw = targetyaw;
523 victim->victim = this->shared_from_this();
530 * GameTick/doPlayerCollisions - spread fire between players
531 * GameTick/doDevKeys - press f to ignite
532 * Person::DoStuff - spread fire from lit campfires and bushes
534 void Person::CatchFire()
536 XYZ flatfacing, flatvelocity;
538 for (int i = 0; i < 10; i++) {
539 howmany = fabs(Random() % (skeleton.joints.size()));
541 flatvelocity = skeleton.joints[howmany].velocity;
542 flatfacing = skeleton.joints[howmany].position * scale + coords;
544 flatvelocity = velocity;
545 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
547 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
552 emit_sound_at(firestartsound, coords);
554 emit_stream_at(stream_firesound, coords);
562 * idle animation for this creature (depending on status)
564 int Person::getIdle()
566 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
568 if (hasvictim && (victim != this->shared_from_this())) {
569 if ((!victim->dead && victim->aitype != passivetype &&
570 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
571 victim->id < Person::players.size())) {
572 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
573 if (creature == rabbittype)
574 return fightidleanim;
575 if (creature == wolftype)
578 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
579 if (weapons[weaponids[weaponactive]].getType() == knife)
580 return knifefightidleanim;
581 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
582 return swordfightidlebothanim;
583 if (weapons[weaponids[weaponactive]].getType() == sword)
584 return swordfightidleanim;
585 if (weapons[weaponids[weaponactive]].getType() == staff)
586 return swordfightidleanim;
588 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
589 return fightsidestep;
592 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
594 if (howactive == typesitting) return sitanim;
595 if (howactive == typesittingwall) return sitwallanim;
596 if (howactive == typesleeping) return sleepanim;
597 if (howactive == typedead1) return dead1anim;
598 if (howactive == typedead2) return dead2anim;
599 if (howactive == typedead3) return dead3anim;
600 if (howactive == typedead4) return dead4anim;
601 if (creature == rabbittype) return bounceidleanim;
602 if (creature == wolftype) return wolfidle;
607 * crouch animation for this creature
609 int Person::getCrouch()
611 if (creature == rabbittype)
613 if (creature == wolftype)
614 return wolfcrouchanim;
619 * running animation for this creature (can be upright or all fours)
623 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
625 if (creature == wolftype && (!superruntoggle))
628 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
629 return rabbitrunninganim;
630 if (creature == wolftype && (superruntoggle))
631 return wolfrunninganim;
637 int Person::getStop()
639 if (creature == rabbittype)
641 if (creature == wolftype)
648 int Person::getLanding()
650 if (creature == rabbittype)
652 if (creature == wolftype)
659 int Person::getLandhard()
661 if (creature == rabbittype)
663 if (creature == wolftype)
664 return wolflandhardanim;
671 * Person::DoAnimations
674 SolidHitBonus(int playerid)
676 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
677 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
679 award_bonus(playerid, solidhit);
683 * spawns blood effects
685 void Person::DoBlood(float howmuch, int which)
687 // FIXME: should abstract out inputs
688 static int bleedxint, bleedyint;
690 if (bloodtoggle && !Tutorial::active) {
691 if (bleeding <= 0 && spurt) {
693 for (int i = 0; i < 3; i++) {
694 // emit blood particles
697 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
698 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
699 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
700 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
703 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
704 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
705 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
706 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
709 if (Random() % 2 == 0) // 50% chance
710 for (int i = 0; i < 3; i++) {
711 if (Random() % 2 != 0) {
712 // emit teeth particles
715 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
716 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
719 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
720 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
724 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
726 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
728 Sprite::setLastSpriteSpecial(3); // sets it to teeth
733 // FIXME: manipulating attributes
734 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
737 if (creature == rabbittype)
738 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
739 bleedxint = abs(Random() % 512);
740 bleedyint = abs(Random() % 512);
742 if (creature == wolftype)
743 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
744 bleedxint = abs(Random() % 512);
745 bleedyint = abs(Random() % 512);
749 bleedy /= realtexdetail;
750 bleedx /= realtexdetail;
751 direction = abs(Random() % 2) * 2 - 1;
760 * spawns big blood effects and ???
761 * modifies character's skin texture
763 void Person::DoBloodBig(float howmuch, int which)
765 static int bleedxint, bleedyint, i, j;
767 if (howmuch && id == 0)
770 if (!Tutorial::active || id == 0)
771 if (aitype != playercontrolled && howmuch > 0) {
775 if (creature == wolftype) {
776 int i = abs(Random() % 2);
778 whichsound = snarlsound;
780 whichsound = snarl2sound;
782 if (creature == rabbittype) {
783 int i = abs(Random() % 2);
785 whichsound = rabbitpainsound;
786 if (i == 1 && howmuch >= 2)
787 whichsound = rabbitpain1sound;
790 if (whichsound != -1) {
791 emit_sound_at(whichsound, coords);
796 if (id == 0 && howmuch > 0) {
800 if (bloodtoggle && decalstoggle && !Tutorial::active) {
801 if (bleeding <= 0 && spurt) {
803 for (int i = 0; i < 3; i++) {
804 // emit blood particles
805 // FIXME: copypaste from above
808 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
809 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
810 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
811 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
814 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
815 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
816 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
817 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
822 // weird texture manipulation code follows.
823 // looks like this is painting blood onto the character's skin texture
824 // FIXME: surely there's a better way
826 int offsetx = 0, offsety = 0;
828 offsety = Random() % 40;
829 offsetx = abs(Random() % 60);
831 if (which == 190 || which == 185) {
832 offsety = Random() % 40;
833 offsetx = abs(Random() % 100) - 20;
836 offsety = Random() % 10;
837 offsetx = Random() % 10;
840 offsety = Random() % 20;
841 offsetx = Random() % 20;
843 if (which == 220 || which == 215) {
853 if (creature == rabbittype)
854 for (i = 0; i < 512; i++) {
855 for (j = 0; j < 512; j++) {
856 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
857 if (i < startx) startx = i;
858 if (j < starty) starty = j;
859 if (i > endx) endx = i;
860 if (j > endy) endy = j;
864 if (creature == wolftype)
865 for (i = 0; i < 512; i++) {
866 for (j = 0; j < 512; j++) {
867 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
868 if (i < startx) startx = i;
869 if (j < starty) starty = j;
870 if (i > endx) endx = i;
871 if (j > endy) endy = j;
881 if (startx < 0) startx = 0;
882 if (starty < 0) starty = 0;
883 if (endx > 512 - 1) endx = 512 - 1;
884 if (endy > 512 - 1) endy = 512 - 1;
885 if (endx < startx) endx = startx;
886 if (endy < starty) endy = starty;
888 startx /= realtexdetail;
889 starty /= realtexdetail;
890 endx /= realtexdetail;
891 endy /= realtexdetail;
893 int texdetailint = realtexdetail;
895 if (creature == rabbittype)
896 for (i = startx; i < endx; i++) {
897 for (j = starty; j < endy; j++) {
898 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
899 color = Random() % 85 + 170;
900 where = i * skeleton.skinsize * 3 + j * 3;
901 if (skeleton.skinText[where + 0] > color / 2)
902 skeleton.skinText[where + 0] = color / 2;
903 skeleton.skinText[where + 1] = 0;
904 skeleton.skinText[where + 2] = 0;
908 if (creature == wolftype)
909 for (i = startx; i < endx; i++) {
910 for (j = starty; j < endy; j++) {
911 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
912 color = Random() % 85 + 170;
913 where = i * skeleton.skinsize * 3 + j * 3;
914 if (skeleton.skinText[where + 0] > color / 2)
915 skeleton.skinText[where + 0] = color / 2;
916 skeleton.skinText[where + 1] = 0;
917 skeleton.skinText[where + 2] = 0;
921 skeleton.drawmodel.textureptr.bind();
926 if (creature == rabbittype)
927 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
928 bleedxint = abs(Random() % 512);
929 bleedyint = abs(Random() % 512);
931 if (creature == wolftype)
932 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
933 bleedxint = abs(Random() % 512);
934 bleedyint = abs(Random() % 512);
936 bleedy = bleedxint + offsetx;
937 bleedx = bleedyint + offsety;
938 bleedy /= realtexdetail;
939 bleedx /= realtexdetail;
944 if (bleedx > skeleton.skinsize - 1)
945 bleedx = skeleton.skinsize - 1;
946 if (bleedy > skeleton.skinsize - 1)
947 bleedy = skeleton.skinsize - 1;
948 direction = abs(Random() % 2) * 2 - 1;
951 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
952 deathbleeding += bleeding;
953 bloodloss += bleeding * 3;
955 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
956 if (abs(Random() % 2) == 0) {
957 aitype = gethelptype;
960 aitype = attacktypecutoff;
968 * similar to DoBloodBig
970 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
974 static XYZ startpoint, endpoint, colpoint, movepoint;
975 static float rotationpoint;
977 static XYZ p1, p2, p3, p0;
980 float coordsx, coordsy;
983 if (bloodtoggle && decalstoggle && !Tutorial::active) {
986 where = DoRotation(where, 0, -yaw, 0);
994 // ray testing for a tri in the character model
995 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
996 if (whichtri != -1) {
997 // low level geometry math
999 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1000 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1001 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1003 bary.x = distsq(&p0, &p1);
1004 bary.y = distsq(&p0, &p2);
1005 bary.z = distsq(&p0, &p3);
1007 total = bary.x + bary.y + bary.z;
1012 bary.x = 1 - bary.x;
1013 bary.y = 1 - bary.y;
1014 bary.z = 1 - bary.z;
1016 total = bary.x + bary.y + bary.z;
1022 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1023 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1024 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1025 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1026 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1027 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1028 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;
1029 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;
1031 if (bleeding <= 0 && spurt) {
1033 for (int i = 0; i < 3; i++) {
1034 // emit blood particles
1035 // FIXME: more copypaste code
1037 if (skeleton.free) {
1038 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1039 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1040 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1041 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1044 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1045 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1046 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1047 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1052 // texture manipulation follows
1054 int offsetx = 0, offsety = 0;
1055 offsetx = (1 + coordsy) * 512 - 291;
1056 offsety = coordsx * 512 - 437;
1063 if (creature == rabbittype)
1064 for (i = 0; i < 512; i++) {
1065 for (j = 0; j < 512; j++) {
1066 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1067 if (i < startx) startx = i;
1068 if (j < starty) starty = j;
1069 if (i > endx) endx = i;
1070 if (j > endy) endy = j;
1074 if (creature == wolftype)
1075 for (i = 0; i < 512; i++) {
1076 for (j = 0; j < 512; j++) {
1077 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1078 if (i < startx) startx = i;
1079 if (j < starty) starty = j;
1080 if (i > endx) endx = i;
1081 if (j > endy) endy = j;
1090 if (startx < 0) startx = 0;
1091 if (starty < 0) starty = 0;
1092 if (endx > 512 - 1) endx = 512 - 1;
1093 if (endy > 512 - 1) endy = 512 - 1;
1094 if (endx < startx) endx = startx;
1095 if (endy < starty) endy = starty;
1097 startx /= realtexdetail;
1098 starty /= realtexdetail;
1099 endx /= realtexdetail;
1100 endy /= realtexdetail;
1102 int texdetailint = realtexdetail;
1104 if (creature == rabbittype)
1105 for (i = startx; i < endx; i++) {
1106 for (j = starty; j < endy; j++) {
1107 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1108 color = Random() % 85 + 170;
1109 where = i * skeleton.skinsize * 3 + j * 3;
1110 if (skeleton.skinText[where + 0] > color / 2)
1111 skeleton.skinText[where + 0] = color / 2;
1112 skeleton.skinText[where + 1] = 0;
1113 skeleton.skinText[where + 2] = 0;
1114 } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1115 color = Random() % 85 + 170;
1116 where = i * skeleton.skinsize * 3 + j * 3;
1117 if (skeleton.skinText[where + 0] > color / 2)
1118 skeleton.skinText[where + 0] = color / 2;
1119 skeleton.skinText[where + 1] = 0;
1120 skeleton.skinText[where + 2] = 0;
1124 if (creature == wolftype)
1125 for (i = startx; i < endx; i++) {
1126 for (j = starty; j < endy; j++) {
1127 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1128 color = Random() % 85 + 170;
1129 where = i * skeleton.skinsize * 3 + j * 3;
1130 if (skeleton.skinText[where + 0] > color / 2)
1131 skeleton.skinText[where + 0] = color / 2;
1132 skeleton.skinText[where + 1] = 0;
1133 skeleton.skinText[where + 2] = 0;
1134 } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1135 color = Random() % 85 + 170;
1136 where = i * skeleton.skinsize * 3 + j * 3;
1137 if (skeleton.skinText[where + 0] > color / 2)
1138 skeleton.skinText[where + 0] = color / 2;
1139 skeleton.skinText[where + 1] = 0;
1140 skeleton.skinText[where + 2] = 0;
1144 skeleton.drawmodel.textureptr.bind();
1147 bleedy = (1 + coordsy) * 512;
1148 bleedx = coordsx * 512;
1149 bleedy /= realtexdetail;
1150 bleedx /= realtexdetail;
1155 if (bleedx > skeleton.skinsize - 1)
1156 bleedx = skeleton.skinsize - 1;
1157 if (bleedy > skeleton.skinsize - 1)
1158 bleedy = skeleton.skinsize - 1;
1159 direction = abs(Random() % 2) * 2 - 1;
1164 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1165 deathbleeding += bleeding;
1166 bloodloss += bleeding * 3;
1168 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1169 if (abs(Random() % 2) == 0) {
1170 aitype = gethelptype;
1173 aitype = attacktypecutoff;
1184 * guessing this performs a reversal
1186 void Person::Reverse()
1188 if (!((victim->aitype == playercontrolled
1190 || staggerdelay <= 0)
1191 && victim->animTarget != jumpupanim
1192 && victim->animTarget != jumpdownanim
1193 && (!Tutorial::active || cananger)
1197 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1198 && (victim->id != 0 || difficulty >= 2)
1199 && (creature != wolftype || victim->creature == wolftype))
1202 if (animTarget == sweepanim) {
1203 animTarget = sweepreversedanim;
1204 animCurrent = sweepreversedanim;
1205 victim->animCurrent = sweepreversalanim;
1206 victim->animTarget = sweepreversalanim;
1208 if (animTarget == spinkickanim) {
1209 animTarget = spinkickreversedanim;
1210 animCurrent = spinkickreversedanim;
1211 victim->animCurrent = spinkickreversalanim;
1212 victim->animTarget = spinkickreversalanim;
1214 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1215 if (animTarget == rabbittacklinganim) {
1218 victim->frameCurrent = 6;
1219 victim->frameTarget = 7;
1221 animTarget = upunchreversedanim;
1222 animCurrent = upunchreversedanim;
1223 victim->animCurrent = upunchreversalanim;
1224 victim->animTarget = upunchreversalanim;
1226 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1227 if (victim->weaponactive != -1) {
1228 victim->throwtogglekeydown = 1;
1229 XYZ tempVelocity = victim->velocity * .2;
1230 if (tempVelocity.x == 0)
1231 tempVelocity.x = .1;
1232 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1233 victim->num_weapons--;
1234 if (victim->num_weapons) {
1235 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1236 if (victim->weaponstuck == victim->num_weapons)
1237 victim->weaponstuck = 0;
1240 victim->weaponactive = -1;
1241 for (unsigned j = 0; j < Person::players.size(); j++) {
1242 Person::players[j]->wentforweapon = 0;
1246 animTarget = staffhitreversedanim;
1247 animCurrent = staffhitreversedanim;
1248 victim->animCurrent = staffhitreversalanim;
1249 victim->animTarget = staffhitreversalanim;
1251 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1252 if (victim->weaponactive != -1) {
1253 victim->throwtogglekeydown = 1;
1254 XYZ tempVelocity = victim->velocity * .2;
1255 if (tempVelocity.x == 0)
1256 tempVelocity.x = .1;
1257 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1258 victim->num_weapons--;
1259 if (victim->num_weapons) {
1260 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1261 if (victim->weaponstuck == victim->num_weapons)
1262 victim->weaponstuck = 0;
1265 victim->weaponactive = -1;
1266 for (unsigned j = 0; j < Person::players.size(); j++) {
1267 Person::players[j]->wentforweapon = 0;
1270 animTarget = staffspinhitreversedanim;
1271 animCurrent = staffspinhitreversedanim;
1272 victim->animCurrent = staffspinhitreversalanim;
1273 victim->animTarget = staffspinhitreversalanim;
1275 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1276 if (victim->weaponactive != -1) {
1277 victim->throwtogglekeydown = 1;
1278 XYZ tempVelocity = victim->velocity * .2;
1279 if (tempVelocity.x == 0)
1280 tempVelocity.x = .1;
1281 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1282 victim->num_weapons--;
1283 if (victim->num_weapons) {
1284 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1285 if (victim->weaponstuck == victim->num_weapons)
1286 victim->weaponstuck = 0;
1289 victim->weaponactive = -1;
1290 for (unsigned j = 0; j < Person::players.size(); j++) {
1291 Person::players[j]->wentforweapon = 0;
1294 animTarget = swordslashreversedanim;
1295 animCurrent = swordslashreversedanim;
1296 victim->animCurrent = swordslashreversalanim;
1297 victim->animTarget = swordslashreversalanim;
1299 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1300 if (victim->weaponactive != -1) {
1301 victim->throwtogglekeydown = 1;
1302 XYZ tempVelocity = victim->velocity * .2;
1303 if (tempVelocity.x == 0)
1304 tempVelocity.x = .1;
1305 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1306 victim->num_weapons--;
1307 if (victim->num_weapons) {
1308 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1309 if (victim->weaponstuck == victim->num_weapons)
1310 victim->weaponstuck = 0;
1313 victim->weaponactive = -1;
1314 for (unsigned j = 0; j < Person::players.size(); j++) {
1315 Person::players[j]->wentforweapon = 0;
1318 animTarget = knifeslashreversedanim;
1319 animCurrent = knifeslashreversedanim;
1320 victim->animCurrent = knifeslashreversalanim;
1321 victim->animTarget = knifeslashreversalanim;
1323 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1324 victim->targettilt2 = targettilt2;
1325 victim->frameCurrent = frameCurrent;
1326 victim->frameTarget = frameTarget;
1327 victim->target = target;
1328 victim->velocity = 0;
1329 victim->oldcoords = victim->coords;
1330 victim->coords = coords;
1331 victim->targetyaw = targetyaw;
1332 victim->yaw = targetyaw;
1333 victim->victim = this->shared_from_this();
1335 if (animTarget == winduppunchanim) {
1336 animTarget = winduppunchblockedanim;
1337 victim->animTarget = blockhighleftanim;
1338 victim->frameTarget = 1;
1339 victim->target = .5;
1340 victim->victim = this->shared_from_this();
1341 victim->targetyaw = targetyaw + 180;
1343 if (animTarget == wolfslapanim) {
1344 animTarget = winduppunchblockedanim;
1345 victim->animTarget = blockhighleftanim;
1346 victim->frameTarget = 1;
1347 victim->target = .5;
1348 victim->victim = this->shared_from_this();
1349 victim->targetyaw = targetyaw + 180;
1351 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1352 animTarget = swordslashparriedanim;
1353 parriedrecently = .4;
1354 victim->parriedrecently = 0;
1355 victim->animTarget = swordslashparryanim;
1356 victim->frameTarget = 1;
1357 victim->target = .5;
1358 victim->victim = this->shared_from_this();
1359 victim->targetyaw = targetyaw + 180;
1361 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1362 if (victim->weaponactive != -1) {
1363 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1364 if (weapons[victim->weaponids[0]].getType() == staff)
1365 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1366 if (weapons[weaponids[0]].getType() == staff)
1367 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1368 emit_sound_at(swordstaffsound, victim->coords);
1370 emit_sound_at(metalhitsound, victim->coords);
1374 victim->Puff(righthand);
1376 victim->frameTarget = 0;
1377 victim->animTarget = staggerbackhighanim;
1378 victim->targetyaw = targetyaw + 180;
1380 aim = DoRotation(facing, 0, 90, 0) * 21;
1382 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1383 victim->num_weapons--;
1384 if (victim->num_weapons) {
1385 victim->weaponids[0] = victim->weaponids[num_weapons];
1386 if (victim->weaponstuck == victim->num_weapons)
1387 victim->weaponstuck = 0;
1389 victim->weaponactive = -1;
1390 for (unsigned i = 0; i < Person::players.size(); i++) {
1391 Person::players[i]->wentforweapon = 0;
1395 if (abs(Random() % 20) == 0) {
1396 if (weaponactive != -1) {
1397 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1398 if (weapons[victim->weaponids[0]].getType() == staff)
1399 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1400 if (weapons[weaponids[0]].getType() == staff)
1401 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1403 emit_sound_at(swordstaffsound, coords);
1405 emit_sound_at(metalhitsound, coords);
1413 animTarget = staggerbackhighanim;
1414 targetyaw = targetyaw + 180;
1416 aim = DoRotation(facing, 0, 90, 0) * 21;
1418 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1421 weaponids[0] = weaponids[num_weapons];
1422 if (weaponstuck == num_weapons)
1426 for (unsigned i = 0; i < Person::players.size(); i++) {
1427 Person::players[i]->wentforweapon = 0;
1434 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1435 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1436 victim->animTarget = dodgebackanim;
1437 victim->frameTarget = 0;
1441 rotatetarget = coords - victim->coords;
1442 Normalise(&rotatetarget);
1443 victim->targetyaw = -asin(0 - rotatetarget.x);
1444 victim->targetyaw *= 360 / 6.28;
1445 if (rotatetarget.z < 0)
1446 victim->targetyaw = 180 - victim->targetyaw;
1448 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1450 victim->lastattack3 = victim->lastattack2;
1451 victim->lastattack2 = victim->lastattack;
1452 victim->lastattack = victim->animTarget;
1454 victim->animTarget = sweepanim;
1455 victim->frameTarget = 0;
1459 rotatetarget = coords - victim->coords;
1460 Normalise(&rotatetarget);
1461 victim->targetyaw = -asin(0 - rotatetarget.x);
1462 victim->targetyaw *= 360 / 6.28;
1463 if (rotatetarget.z < 0)
1464 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;
1475 victim->velocity = 0;
1477 if (aitype != playercontrolled) {
1479 if (escapednum < 2) {
1480 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1481 if ((Random() % chances) == 0) {
1487 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1494 void Person::DoDamage(float howmuch)
1498 damagetaken += howmuch / power;
1500 damagedealt += howmuch / power;
1504 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1509 if (!Tutorial::active) {
1510 damage += howmuch / power;
1511 permanentdamage += howmuch / 2 / power;
1512 superpermanentdamage += howmuch / 4 / power;
1515 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1517 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1521 camerashake += howmuch / 100;
1522 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1523 blackout = damage / damagetolerance;
1531 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile))
1532 aitype = attacktypecutoff;
1533 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1534 if (abs(Random() % 2) == 0) {
1535 aitype = gethelptype;
1538 aitype = attacktypecutoff;
1542 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1545 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1546 if (skeleton.free) {
1547 flatvelocity2 = skeleton.joints[i].velocity;
1548 flatfacing2 = skeleton.joints[i].position * scale + coords;
1550 flatvelocity2 = velocity;
1551 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1553 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1554 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1555 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1556 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1557 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1558 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1561 emit_sound_at(splattersound, coords);
1566 if (!dead && creature == wolftype) {
1567 award_bonus(0, Wolfbonus);
1574 if (!Tutorial::active || id == 0) {
1575 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1576 int whichsound = -1;
1578 if (creature == wolftype) {
1579 int i = abs(Random() % 2);
1581 whichsound = snarlsound;
1583 whichsound = snarl2sound;
1585 if (creature == rabbittype) {
1586 int i = abs(Random() % 2);
1588 whichsound = rabbitpainsound;
1589 if (i == 1 && damage > damagetolerance)
1590 whichsound = rabbitpain1sound;
1593 if (whichsound != -1) {
1594 emit_sound_at(whichsound, coords);
1595 addEnvSound(coords);
1603 * calculate/animate head facing direction?
1605 void Person::DoHead()
1607 static XYZ rotatearound;
1609 static float lookspeed = 500;
1611 if (!freeze && !winfreeze) {
1614 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1615 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1617 while (targetheadyaw > 180)targetheadyaw -= 360;
1618 while (targetheadyaw < -180)targetheadyaw += 360;
1620 if (targetheadyaw > 160)
1621 targetheadpitch = targetheadpitch * -1;
1622 if (targetheadyaw < -160)
1623 targetheadpitch = targetheadpitch * -1;
1624 if (targetheadyaw > 160)
1625 targetheadyaw = targetheadyaw - 180;
1626 if (targetheadyaw < -160)
1627 targetheadyaw = targetheadyaw + 180;
1629 if (targetheadpitch > 120)
1630 targetheadpitch = 120;
1631 if (targetheadpitch < -120)
1632 targetheadpitch = -120;
1633 if (targetheadyaw > 120)
1634 targetheadyaw = 120;
1635 if (targetheadyaw < -120)
1636 targetheadyaw = -120;
1639 targetheadpitch = 0;
1641 if (targetheadyaw > 80)
1643 if (targetheadyaw < -80)
1644 targetheadyaw = -80;
1645 if (targetheadpitch > 50)
1646 targetheadpitch = 50;
1647 if (targetheadpitch < -50)
1648 targetheadpitch = -50;
1651 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1652 headyaw = targetheadyaw;
1653 else if (headyaw > targetheadyaw) {
1654 headyaw -= multiplier * lookspeed;
1655 } else if (headyaw < targetheadyaw) {
1656 headyaw += multiplier * lookspeed;
1659 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1660 headpitch = targetheadpitch;
1661 else if (headpitch > targetheadpitch) {
1662 headpitch -= multiplier * lookspeed / 2;
1663 } else if (headpitch < targetheadpitch) {
1664 headpitch += multiplier * lookspeed / 2;
1667 rotatearound = jointPos(neck);
1668 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1672 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1673 facing = DoRotation(facing, headpitch * .4, 0, 0);
1674 facing = DoRotation(facing, 0, headyaw * .4, 0);
1677 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1678 facing = DoRotation(facing, headpitch * .8, 0, 0);
1679 facing = DoRotation(facing, 0, headyaw * .8, 0);
1682 if (animTarget == walkanim) {
1683 facing = DoRotation(facing, headpitch * .6, 0, 0);
1684 facing = DoRotation(facing, 0, headyaw * .6, 0);
1687 skeleton.specialforward[0] = facing;
1688 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1689 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1690 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1691 skeleton.FindRotationMuscle(i, animTarget);
1698 * ragdolls character?
1700 void Person::RagDoll(bool checkcollision)
1705 if (!skeleton.free) {
1708 if (id == 0 && isFlip())
1715 facing = DoRotation(facing, 0, yaw, 0);
1717 skeleton.freetime = 0;
1719 skeleton.longdead = 0;
1722 skeleton.broken = 0;
1723 skeleton.spinny = 1;
1725 skeleton.freefall = 1;
1727 if (!isnormal(velocity.x)) velocity.x = 0;
1728 if (!isnormal(velocity.y)) velocity.y = 0;
1729 if (!isnormal(velocity.z)) velocity.z = 0;
1730 if (!isnormal(yaw)) yaw = 0;
1731 if (!isnormal(coords.x)) coords = 0;
1732 if (!isnormal(tilt)) tilt = 0;
1733 if (!isnormal(tilt2)) tilt2 = 0;
1735 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1736 skeleton.joints[i].delay = 0;
1737 skeleton.joints[i].locked = 0;
1738 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1739 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1740 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1741 skeleton.joints[i].position.y += .1;
1742 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1743 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1746 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1747 skeleton.joints[i].velocity = 0;
1748 skeleton.joints[i].velchange = 0;
1750 skeleton.DoConstraints(&coords, &scale);
1751 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1752 skeleton.DoConstraints(&coords, &scale);
1753 skeleton.DoConstraints(&coords, &scale);
1754 skeleton.DoConstraints(&coords, &scale);
1755 skeleton.DoConstraints(&coords, &scale);
1758 speed = targetFrame().speed * 2;
1759 if (currentFrame().speed > targetFrame().speed) {
1760 speed = currentFrame().speed * 2;
1763 speed = transspeed * 2;
1767 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1768 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1769 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);
1771 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1772 change.x = (float)(Random() % 100) / 100;
1773 change.y = (float)(Random() % 100) / 100;
1774 change.z = (float)(Random() % 100) / 100;
1775 skeleton.joints[i].velocity += change;
1776 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1778 change.x = (float)(Random() % 100) / 100;
1779 change.y = (float)(Random() % 100) / 100;
1780 change.z = (float)(Random() % 100) / 100;
1781 skeleton.joints[i].velchange += change;
1782 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1785 if (checkcollision) {
1788 if (!skeleton.joints.empty()) {
1791 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1792 average += skeleton.joints[j].position;
1794 average /= skeleton.joints.size();
1795 coords += average * scale;
1796 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1797 skeleton.joints[j].position -= average;
1801 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1802 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1803 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1804 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1807 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1808 coords.x = lowpoint.x;
1809 coords.z = lowpoint.z;
1818 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1819 velocity += skeleton.joints[i].velocity * scale;
1821 velocity /= skeleton.joints.size();
1824 if (Random() % 2 == 0) {
1825 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1826 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1827 weapons[weaponids[0]].velocity.x += .01;
1830 weaponids[0] = weaponids[num_weapons];
1831 if (weaponstuck == num_weapons)
1835 for (unsigned i = 0; i < Person::players.size(); i++) {
1836 Person::players[i]->wentforweapon = 0;
1841 animTarget = bounceidleanim;
1842 animCurrent = bounceidleanim;
1852 void Person::FootLand(bodypart whichfoot, float opacity)
1854 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1855 cerr << "FootLand called on wrong bodypart" << endl;
1858 static XYZ terrainlight;
1859 static XYZ footvel, footpoint;
1860 if (opacity >= 1 || skiddelay <= 0) {
1863 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1864 if (distsq(&footpoint, &viewer))
1865 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1866 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1867 footvel = velocity / 5;
1870 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1871 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1872 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1873 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1874 if (environment == snowyenvironment) {
1875 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1877 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1879 } else if (environment == grassyenvironment) {
1880 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1881 } else if (environment == desertenvironment) {
1882 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1884 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1888 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1889 footvel = velocity / 5;
1892 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1893 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1894 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1901 * make a puff effect at a body part (dust effect?)
1903 void Person::Puff(int whichlabel)
1905 static XYZ footvel, footpoint;
1908 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1909 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1913 * I think I added this in an attempt to clean up code
1915 void Person::setTargetAnimation(int animation)
1917 animTarget = animation;
1926 void Person::DoAnimations()
1928 if (!skeleton.free) {
1929 static float oldtarget;
1931 if (isIdle() && animCurrent != getIdle())
1932 normalsupdatedelay = 0;
1934 if (animTarget == tempanim || animCurrent == tempanim) {
1935 Animation::animations[tempanim] = tempanimation;
1937 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1943 vel[0] = velocity.x;
1944 vel[1] = velocity.y;
1945 vel[2] = velocity.z;
1948 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
1949 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1951 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1953 if (!crouchkeydown && velocity.y >= -15)
1956 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1961 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1963 if (normaldotproduct(targfacing, velocity) >= -.3)
1964 animTarget = flipanim;
1966 animTarget = backflipanim;
1967 crouchtogglekeydown = 1;
1975 if (Animation::animations[animTarget].attack != reversed)
1977 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1978 crouchtogglekeydown = 0;
1979 if (aitype == playercontrolled)
1982 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1985 crouchtogglekeydown = 1;
1989 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1991 normalsupdatedelay = 0;
1995 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1997 emit_sound_at(fireendsound, coords);
1998 pause_sound(stream_firesound);
2002 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2003 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
2005 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2006 if (normaldotproduct(victim->facing, facing) > 0)
2007 victim->animTarget = rabbittackledbackanim;
2009 victim->animTarget = rabbittackledfrontanim;
2010 victim->frameTarget = 2;
2013 victim->targetyaw = yaw;
2014 if (victim->aitype == gethelptype)
2015 victim->DoDamage(victim->damagetolerance - victim->damage);
2016 //victim->DoDamage(30);
2017 if (creature == wolftype) {
2019 emit_sound_at(clawslicesound, victim->coords);
2021 victim->DoBloodBig(1 / victim->armorhead, 210);
2023 award_bonus(id, TackleBonus,
2024 victim->aitype == gethelptype ? 50 : 0);
2028 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2029 if (weapons[weaponids[0]].getType() == knife) {
2030 if (weaponactive == -1)
2032 else if (weaponactive == 0)
2035 if (weaponactive == -1) {
2036 emit_sound_at(knifesheathesound, coords);
2038 if (weaponactive != -1) {
2039 emit_sound_at(knifedrawsound, coords, 128);
2042 drawtogglekeydown = 1;
2045 if (!Tutorial::active || id == 0)
2046 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2047 int whichsound = -1;
2049 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2050 if (targetFrame().label == 1)
2051 whichsound = footstepsound;
2053 whichsound = footstepsound2;
2054 if (targetFrame().label == 1)
2055 FootLand(leftfoot, 1);
2056 if (targetFrame().label == 2)
2057 FootLand(rightfoot, 1);
2058 if (targetFrame().label == 3 && isRun()) {
2059 FootLand(rightfoot, 1);
2060 FootLand(leftfoot, 1);
2064 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2065 if (targetFrame().label == 1)
2066 whichsound = footstepsound3;
2068 whichsound = footstepsound4;
2072 if (targetFrame().label == 1)
2073 whichsound = footstepsound3;
2075 whichsound = footstepsound4;
2077 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2078 if (Animation::animations[animTarget].attack != neutral) {
2079 unsigned r = abs(Random() % 3);
2081 whichsound = lowwhooshsound;
2083 whichsound = midwhooshsound;
2085 whichsound = highwhooshsound;
2087 if (Animation::animations[animTarget].attack == neutral) {
2088 whichsound = movewhooshsound;
2090 } else if (targetFrame().label == 4) {
2091 whichsound = knifeswishsound;
2093 if (targetFrame().label == 8 && !Tutorial::active) {
2094 whichsound = landsound2;
2097 if (whichsound != -1) {
2098 emit_sound_at(whichsound, coords, 256.);
2101 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2102 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2103 addEnvSound(coords, 15);
2105 addEnvSound(coords, 6);
2110 if (targetFrame().label == 3) {
2112 emit_sound_at(whichsound, coords, 128.);
2118 if (!Tutorial::active || id == 0)
2119 if (speechdelay <= 0)
2120 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2121 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2122 int whichsound = -1;
2123 if (targetFrame().label == 4 && aitype != playercontrolled) {
2124 if (Animation::animations[animTarget].attack != neutral) {
2125 unsigned r = abs(Random() % 4);
2126 if (creature == rabbittype) {
2127 if (r == 0) whichsound = rabbitattacksound;
2128 if (r == 1) whichsound = rabbitattack2sound;
2129 if (r == 2) whichsound = rabbitattack3sound;
2130 if (r == 3) whichsound = rabbitattack4sound;
2132 if (creature == wolftype) {
2133 if (r == 0) whichsound = barksound;
2134 if (r == 1) whichsound = bark2sound;
2135 if (r == 2) whichsound = bark3sound;
2136 if (r == 3) whichsound = barkgrowlsound;
2142 if (whichsound != -1) {
2143 emit_sound_at(whichsound, coords);
2149 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2150 FootLand(leftfoot, 1);
2151 FootLand(rightfoot, 1);
2155 currentoffset = targetoffset;
2156 frameTarget = frameCurrent;
2157 animCurrent = animTarget;
2160 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2161 for (unsigned i = 0; i < weapons.size(); i++) {
2162 if (weapons[i].owner == -1)
2163 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2164 if (distsq(&coords, &weapons[i].position) >= 1) {
2165 if (weapons[i].getType() != staff) {
2166 emit_sound_at(knifedrawsound, coords, 128.);
2175 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2176 for (unsigned i = 0; i < weapons.size(); i++) {
2177 bool willwork = true;
2178 if (weapons[i].owner != -1)
2179 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2180 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2181 if (Person::players[weapons[i].owner]->num_weapons > 1)
2183 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2184 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2185 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2186 bool fleshstuck = false;
2187 if (weapons[i].owner != -1)
2188 if (victim->weaponstuck != -1) {
2189 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2194 emit_sound_at(fleshstabremovesound, coords, 128.);
2196 if (weapons[i].getType() != staff) {
2197 emit_sound_at(knifedrawsound, coords, 128.);
2200 if (weapons[i].owner != -1) {
2201 victim = Person::players[weapons[i].owner];
2202 if (victim->num_weapons == 1)
2203 victim->num_weapons = 0;
2205 victim->num_weapons = 1;
2207 //victim->weaponactive=-1;
2208 victim->skeleton.longdead = 0;
2209 victim->skeleton.free = 1;
2210 victim->skeleton.broken = 0;
2212 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2213 victim->skeleton.joints[j].velchange = 0;
2214 victim->skeleton.joints[j].locked = 0;
2220 Normalise(&relative);
2221 XYZ footvel, footpoint;
2223 footpoint = weapons[i].position;
2224 if (victim->weaponstuck != -1) {
2225 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2227 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2228 weapons[i].bloody = 2;
2229 weapons[i].blooddrip = 5;
2230 victim->weaponstuck = -1;
2233 if (victim->num_weapons > 0) {
2234 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2235 victim->weaponstuck = 0;
2236 if (victim->weaponids[0] == int(i))
2237 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2240 victim->jointVel(abdomen) += relative * 6;
2241 victim->jointVel(neck) += relative * 6;
2242 victim->jointVel(rightshoulder) += relative * 6;
2243 victim->jointVel(leftshoulder) += relative * 6;
2251 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2252 if (weaponactive == -1)
2254 else if (weaponactive == 0) {
2256 if (num_weapons == 2) {
2258 buffer = weaponids[0];
2259 weaponids[0] = weaponids[1];
2260 weaponids[1] = buffer;
2263 if (weaponactive == -1) {
2264 emit_sound_at(knifesheathesound, coords, 128.);
2266 if (weaponactive != -1) {
2267 emit_sound_at(knifedrawsound, coords, 128.);
2272 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2273 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2274 Normalise(&rotatetarget);
2275 targetyaw = -asin(0 - rotatetarget.x);
2276 targetyaw *= 360 / 6.28;
2277 if (rotatetarget.z < 0)
2278 targetyaw = 180 - targetyaw;
2280 if (animTarget == walljumprightkickanim)
2282 if (animTarget == walljumpleftkickanim)
2288 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2291 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2296 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2297 animTarget = rabbittackleanim;
2299 emit_sound_at(jumpsound, coords);
2307 targetloc = velocity;
2308 Normalise(&targetloc);
2309 targetloc += coords;
2310 for (unsigned i = 0; i < Person::players.size(); i++) {
2312 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2313 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2317 if (closestid != -1)
2318 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2320 victim = Person::players[closestid];
2321 coords = victim->coords;
2322 animCurrent = rabbittacklinganim;
2323 animTarget = rabbittacklinganim;
2327 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2328 rotatetarget = coords - victim->coords;
2329 Normalise(&rotatetarget);
2330 targetyaw = -asin(0 - rotatetarget.x);
2331 targetyaw *= 360 / 6.28;
2332 if (rotatetarget.z < 0)
2333 targetyaw = 180 - targetyaw;
2335 if (animTarget != rabbitrunninganim) {
2336 emit_sound_at(jumpsound, coords, 128.);
2342 float damagemult = 1 * power;
2343 if (creature == wolftype)
2344 damagemult = 2.5 * power;
2346 damagemult /= victim->damagetolerance / 200;
2348 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)) {
2349 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2350 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2354 if (Random() % 2 || creature == wolftype) {
2357 if (creature == wolftype)
2360 if (!Tutorial::active) {
2361 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2363 if (creature == wolftype) {
2364 emit_sound_at(clawslicesound, victim->coords, 128.);
2366 victim->DoBloodBig(2 / victim->armorhead, 175);
2370 relative = victim->coords - coords;
2372 Normalise(&relative);
2373 relative = DoRotation(relative, 0, -90, 0);
2374 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2375 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2377 victim->jointVel(head) += relative * damagemult * 200;
2379 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2385 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2386 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2390 if (Random() % 2 || creature == wolftype) {
2392 if (creature == wolftype)
2395 emit_sound_at(whooshhitsound, victim->coords);
2396 if (creature == wolftype) {
2397 emit_sound_at(clawslicesound, victim->coords, 128.);
2399 victim->DoBloodBig(2, 175);
2403 relative = victim->coords - coords;
2405 Normalise(&relative);
2407 Normalise(&relative);
2408 relative = DoRotation(relative, 0, 90, 0);
2409 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2410 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2412 victim->jointVel(head) += relative * damagemult * 100;
2414 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2418 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2419 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2425 if (!Tutorial::active) {
2426 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2428 if (creature == wolftype) {
2429 emit_sound_at(clawslicesound, victim->coords, 128.);
2431 victim->DoBloodBig(2 / victim->armorhead, 175);
2437 Normalise(&relative);
2438 relative = DoRotation(relative, 0, -90, 0);
2439 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2440 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2442 victim->jointVel(head) += relative * damagemult * 200;
2444 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2446 if (victim->damage > victim->damagetolerance)
2447 award_bonus(id, style);
2453 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2454 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2460 if (!Tutorial::active) {
2461 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2463 if (creature == wolftype) {
2464 emit_sound_at(clawslicesound, victim->coords, 128.);
2466 victim->DoBloodBig(2 / victim->armorhead, 175);
2472 Normalise(&relative);
2473 relative = DoRotation(relative, 0, 90, 0);
2474 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2475 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2477 victim->jointVel(head) += relative * damagemult * 200;
2479 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2481 if (victim->damage > victim->damagetolerance)
2482 award_bonus(id, style);
2488 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2489 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2497 emit_sound_at(whooshhitsound, victim->coords);
2500 relative = victim->coords - coords;
2502 Normalise(&relative);
2503 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2504 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2506 victim->jointVel(head) += relative * damagemult * 100;
2508 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2512 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2513 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2517 emit_sound_at(whooshhitsound, victim->coords, 128.);
2519 victim->skeleton.longdead = 0;
2520 victim->skeleton.free = 1;
2521 victim->skeleton.broken = 0;
2522 victim->skeleton.spinny = 1;
2524 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2525 victim->skeleton.joints[i].velchange = 0;
2526 victim->skeleton.joints[i].delay = 0;
2527 victim->skeleton.joints[i].locked = 0;
2528 //victim->skeleton.joints[i].velocity=0;
2534 Normalise(&relative);
2535 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2536 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2537 victim->skeleton.joints[i].position.y += relative.y * .3;
2538 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2539 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2541 victim->Puff(abdomen);
2542 victim->jointVel(abdomen).y = relative.y * 400;
2546 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2547 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2551 if (!Tutorial::active) {
2552 emit_sound_at(heavyimpactsound, coords, 128.);
2555 relative = victim->coords - coords;
2557 Normalise(&relative);
2558 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2559 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2561 victim->Puff(abdomen);
2562 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2566 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2567 victim->jointVel(abdomen) += relative * damagemult * 300;
2571 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2572 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2576 if (!Tutorial::active) {
2577 emit_sound_at(thudsound, coords);
2580 victim->skeleton.longdead = 0;
2581 victim->skeleton.free = 1;
2582 victim->skeleton.broken = 0;
2583 victim->skeleton.spinny = 1;
2585 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2586 victim->skeleton.joints[i].velchange = 0;
2587 //victim->skeleton.joints[i].delay=0;
2588 victim->skeleton.joints[i].locked = 0;
2591 relative = victim->coords - coords;
2592 Normalise(&relative);
2594 Normalise(&relative);
2595 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2596 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2601 victim->Puff(abdomen);
2602 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2603 victim->jointVel(abdomen) += relative * damagemult * 200;
2612 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2615 if (!victim->skeleton.free)
2619 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2620 emit_sound_at(knifesheathesound, coords, 128.);
2623 if (victim && hasvictim) {
2624 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2626 XYZ where, startpoint, endpoint, movepoint, colpoint;
2627 float rotationpoint;
2629 if (weapons[weaponids[weaponactive]].getType() == knife) {
2630 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2631 where -= victim->coords;
2632 if (!victim->skeleton.free)
2633 where = DoRotation(where, 0, -victim->yaw, 0);
2636 startpoint.y += 100;
2640 if (weapons[weaponids[weaponactive]].getType() == sword) {
2641 where = weapons[weaponids[weaponactive]].position;
2642 where -= victim->coords;
2643 if (!victim->skeleton.free)
2644 where = DoRotation(where, 0, -victim->yaw, 0);
2646 where = weapons[weaponids[weaponactive]].tippoint;
2647 where -= victim->coords;
2648 if (!victim->skeleton.free)
2649 where = DoRotation(where, 0, -victim->yaw, 0);
2652 if (weapons[weaponids[weaponactive]].getType() == staff) {
2653 where = weapons[weaponids[weaponactive]].position;
2654 where -= victim->coords;
2655 if (!victim->skeleton.free)
2656 where = DoRotation(where, 0, -victim->yaw, 0);
2658 where = weapons[weaponids[weaponactive]].tippoint;
2659 where -= victim->coords;
2660 if (!victim->skeleton.free)
2661 where = DoRotation(where, 0, -victim->yaw, 0);
2666 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2668 if (whichtri != -1) {
2669 if (victim->dead != 2) {
2670 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2672 award_bonus(id, FinishedBonus);
2675 weapons[weaponids[weaponactive]].bloody = 2;
2677 victim->skeleton.longdead = 0;
2678 victim->skeleton.free = 1;
2679 victim->skeleton.broken = 0;
2681 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2682 victim->skeleton.joints[i].velchange = 0;
2683 victim->skeleton.joints[i].locked = 0;
2684 //victim->skeleton.joints[i].velocity=0;
2686 emit_sound_at(fleshstabsound, coords, 128);
2689 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2690 weapons[weaponids[weaponactive]].blooddrip += 5;
2691 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2693 if (whichtri == -1) {
2695 emit_sound_at(knifesheathesound, coords, 128.);
2701 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2703 emit_sound_at(knifedrawsound, coords, 128);
2706 if (victim && hasvictim) {
2707 XYZ footvel, footpoint;
2709 emit_sound_at(fleshstabremovesound, coords, 128.);
2712 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2714 if (weapons[weaponids[weaponactive]].getType() == sword) {
2715 XYZ where, startpoint, endpoint, movepoint;
2716 float rotationpoint;
2719 where = weapons[weaponids[weaponactive]].position;
2720 where -= victim->coords;
2721 if (!victim->skeleton.free)
2722 where = DoRotation(where, 0, -victim->yaw, 0);
2724 where = weapons[weaponids[weaponactive]].tippoint;
2725 where -= victim->coords;
2726 if (!victim->skeleton.free)
2727 where = DoRotation(where, 0, -victim->yaw, 0);
2732 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2733 footpoint += victim->coords;
2735 if (whichtri == -1) {
2736 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2739 if (weapons[weaponids[weaponactive]].getType() == staff) {
2740 XYZ where, startpoint, endpoint, movepoint;
2741 float rotationpoint;
2744 where = weapons[weaponids[weaponactive]].position;
2745 where -= victim->coords;
2746 if (!victim->skeleton.free)
2747 where = DoRotation(where, 0, -victim->yaw, 0);
2749 where = weapons[weaponids[weaponactive]].tippoint;
2750 where -= victim->coords;
2751 if (!victim->skeleton.free)
2752 where = DoRotation(where, 0, -victim->yaw, 0);
2757 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2758 footpoint += victim->coords;
2760 if (whichtri == -1) {
2761 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2764 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2766 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2767 victim->skeleton.longdead = 0;
2768 victim->skeleton.free = 1;
2769 victim->skeleton.broken = 0;
2771 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2772 victim->skeleton.joints[i].velchange = 0;
2773 victim->skeleton.joints[i].locked = 0;
2774 //victim->skeleton.joints[i].velocity=0;
2780 Normalise(&relative);
2781 //victim->Puff(abdomen);
2783 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2785 if (victim->bloodloss < victim->damagetolerance) {
2786 victim->bloodloss += 1000;
2790 victim->jointVel(abdomen) += relative * damagemult * 20;
2794 if (!hasvictim && onterrain) {
2795 weapons[weaponids[weaponactive]].bloody = 0;
2796 weapons[weaponids[weaponactive]].blooddrip = 0;
2800 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2801 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2809 if (!Tutorial::active) {
2810 emit_sound_at(heavyimpactsound, victim->coords, 128);
2815 relative = victim->coords - coords;
2817 Normalise(&relative);
2818 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2819 victim->skeleton.joints[i].velocity = relative * 30;
2821 victim->jointVel(head) += relative * damagemult * 150;
2823 victim->frameTarget = 0;
2824 victim->animTarget = staggerbackhardanim;
2825 victim->targetyaw = targetyaw + 180;
2827 victim->stunned = 1;
2830 victim->Puff(abdomen);
2831 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2838 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2839 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2843 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2844 if (!Tutorial::active) {
2845 emit_sound_at(thudsound, victim->coords);
2847 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2848 if (!Tutorial::active) {
2849 emit_sound_at(whooshhitsound, victim->coords);
2852 if (!Tutorial::active) {
2853 emit_sound_at(heavyimpactsound, victim->coords);
2857 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2860 relative = victim->coords - coords;
2862 Normalise(&relative);
2864 Normalise(&relative);
2865 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2866 victim->skeleton.joints[i].velocity = relative * 5;
2868 victim->jointVel(abdomen) += relative * damagemult * 400;
2870 victim->frameTarget = 0;
2871 victim->animTarget = staggerbackhardanim;
2872 victim->targetyaw = targetyaw + 180;
2874 victim->stunned = 1;
2876 victim->Puff(abdomen);
2877 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2883 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2884 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2885 if (victim->id == 0)
2887 emit_sound_at(landsound2, victim->coords);
2893 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2894 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2895 if (victim->id == 0)
2898 if (weaponactive != -1) {
2899 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2900 if (weapons[victim->weaponids[0]].getType() == staff)
2901 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2902 if (weapons[weaponids[0]].getType() == staff)
2903 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2905 emit_sound_at(swordstaffsound, victim->coords);
2907 emit_sound_at(metalhitsound, victim->coords);
2915 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2916 if (weaponactive != -1) {
2919 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);
2921 weapons[weaponids[0]].thrown(aim * 50);
2924 weaponids[0] = weaponids[num_weapons];
2930 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2932 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2934 if (!Tutorial::active) {
2935 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2938 award_bonus(id, Slicebonus);
2939 if (!Tutorial::active) {
2940 emit_sound_at(knifeslicesound, victim->coords);
2942 //victim->jointVel(abdomen)+=relative*damagemult*200;
2943 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2944 if (victim->id != 0 || difficulty == 2) {
2945 victim->frameTarget = 0;
2946 victim->animTarget = staggerbackhardanim;
2947 victim->targetyaw = targetyaw + 180;
2951 victim->lowreversaldelay = 0;
2952 victim->highreversaldelay = 0;
2953 if (aitype != playercontrolled)
2954 weaponmissdelay = .6;
2956 if (!Tutorial::active) {
2957 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
2958 weapons[weaponids[weaponactive]].bloody = 1;
2960 weapons[weaponids[weaponactive]].blooddrip += 3;
2963 XYZ footvel, footpoint;
2965 if (skeleton.free) {
2966 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2968 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2970 if (Tutorial::active) {
2971 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2974 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2976 footvel = DoRotation(facing, 0, 90, 0) * .8;
2977 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2978 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2979 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2980 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2982 victim->DoDamage(damagemult * 0);
2985 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2986 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2987 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2988 award_bonus(id, Slashbonus);
2990 if (!Tutorial::active) {
2991 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2992 victim->DoBloodBig(2 / victim->armorhigh, 190);
2994 victim->DoBloodBig(2 / victim->armorhigh, 185);
2995 victim->deathbleeding = 1;
2996 emit_sound_at(swordslicesound, victim->coords);
2997 victim->frameTarget = 0;
2998 victim->animTarget = staggerbackhardanim;
2999 victim->targetyaw = targetyaw + 180;
3001 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3002 weapons[weaponids[weaponactive]].bloody = 1;
3004 weapons[weaponids[weaponactive]].blooddrip += 3;
3006 float bloodlossamount;
3007 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3008 victim->bloodloss += bloodlossamount / victim->armorhigh;
3009 victim->DoDamage(damagemult * 0);
3011 XYZ footvel, footpoint;
3013 if (skeleton.free) {
3014 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3016 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3019 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3021 footvel = DoRotation(facing, 0, 90, 0) * .8;
3023 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3024 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3025 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3026 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3029 if (victim->weaponactive != -1) {
3030 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3031 if (weapons[victim->weaponids[0]].getType() == staff)
3032 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3033 if (weapons[weaponids[0]].getType() == staff)
3034 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3036 emit_sound_at(swordstaffsound, victim->coords);
3038 emit_sound_at(metalhitsound, victim->coords);
3044 victim->Puff(righthand);
3046 victim->frameTarget = 0;
3047 victim->animTarget = staggerbackhighanim;
3048 victim->targetyaw = targetyaw + 180;
3050 aim = DoRotation(facing, 0, 90, 0) * 21;
3052 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3053 victim->num_weapons--;
3054 if (victim->num_weapons) {
3055 victim->weaponids[0] = victim->weaponids[num_weapons];
3056 if (victim->weaponstuck == victim->num_weapons)
3057 victim->weaponstuck = 0;
3059 victim->weaponactive = -1;
3060 for (unsigned i = 0; i < Person::players.size(); i++) {
3061 Person::players[i]->wentforweapon = 0;
3068 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3069 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3070 if (!Tutorial::active) {
3071 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3075 if (Random() % 2 || creature == wolftype) {
3078 emit_sound_at(staffheadsound, victim->coords);
3082 relative = victim->coords - coords;
3084 Normalise(&relative);
3085 relative = DoRotation(relative, 0, 90, 0);
3087 Normalise(&relative);
3088 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3089 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3091 victim->jointVel(head) += relative * damagemult * 230;
3092 victim->jointVel(neck) += relative * damagemult * 230;
3094 if (!Tutorial::active) {
3095 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3097 award_bonus(id, solidhit, 30);
3102 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3103 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3104 if (!Tutorial::active) {
3105 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3109 if (Random() % 2 || creature == wolftype) {
3112 emit_sound_at(staffheadsound, victim->coords);
3116 relative = victim->coords - coords;
3118 Normalise(&relative);
3119 relative = DoRotation(relative, 0, -90, 0);
3120 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3121 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3123 victim->jointVel(head) += relative * damagemult * 220;
3124 victim->jointVel(neck) += relative * damagemult * 220;
3126 if (!Tutorial::active) {
3127 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3129 award_bonus(id, solidhit, 60);
3134 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3135 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3137 if (!Tutorial::active) {
3139 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3142 if (Random() % 2 || creature == wolftype) {
3145 emit_sound_at(staffbodysound, victim->coords);
3147 victim->skeleton.longdead = 0;
3148 victim->skeleton.free = 1;
3149 victim->skeleton.broken = 0;
3151 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3152 victim->skeleton.joints[i].velchange = 0;
3153 victim->skeleton.joints[i].locked = 0;
3154 //victim->skeleton.joints[i].velocity=0;
3161 Normalise(&relative);
3162 if (!victim->dead) {
3163 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3164 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3166 victim->jointVel(abdomen) += relative * damagemult * 40;
3169 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3170 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3173 victim->Puff(abdomen);
3174 if (!Tutorial::active) {
3175 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3177 if (!victim->dead) {
3178 award_bonus(id, solidhit, 40);
3184 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3185 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3190 relative = victim->coords - coords;
3192 Normalise(&relative);
3196 if (Animation::animations[victim->animTarget].height == lowheight) {
3202 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3203 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3205 victim->jointVel(head) += relative * damagemult * 200;
3206 if (!Tutorial::active) {
3207 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3210 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3211 if (victim->howactive == typesleeping)
3212 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3213 if (creature == wolftype) {
3214 emit_sound_at(clawslicesound, victim->coords, 128.);
3216 victim->DoBloodBig(2 / victim->armorhead, 175);
3219 if (victim->damage >= victim->damagetolerance)
3221 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3222 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3224 victim->jointVel(abdomen) += relative * damagemult * 200;
3225 victim->frameTarget = 0;
3226 victim->animTarget = staggerbackhighanim;
3227 victim->targetyaw = targetyaw + 180;
3229 if (!Tutorial::active) {
3230 emit_sound_at(landsound2, victim->coords, 128.);
3232 victim->Puff(abdomen);
3233 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3234 if (creature == wolftype) {
3235 emit_sound_at(clawslicesound, victim->coords, 128.);
3237 victim->DoBloodBig(2 / victim->armorhigh, 170);
3244 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3245 if ((victim->animTarget != jumpupanim) &&
3246 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3247 (victim != this->shared_from_this())) {
3251 if (!Tutorial::active) {
3252 emit_sound_at(landsound2, victim->coords, 128.);
3255 relative = victim->coords - coords;
3257 Normalise(&relative);
3259 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3262 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3263 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3265 relative = DoRotation(relative, 0, -90, 0);
3267 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3268 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)
3269 victim->skeleton.joints[i].velocity = relative * 80;
3271 victim->Puff(rightankle);
3272 victim->Puff(leftankle);
3273 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3275 if (victim->damage >= victim->damagetolerance)
3277 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3278 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3280 relative = DoRotation(relative, 0, -90, 0);
3281 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3282 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)
3283 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3285 victim->jointVel(abdomen) += relative * damagemult * 200;
3286 victim->frameTarget = 0;
3287 victim->animTarget = staggerbackhighanim;
3288 victim->targetyaw = targetyaw + 180;
3290 if (!Tutorial::active) {
3291 emit_sound_at(landsound2, victim->coords, 128.);
3293 victim->Puff(abdomen);
3294 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3302 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3303 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3311 if (!Tutorial::active) {
3312 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3314 if (creature == wolftype) {
3315 emit_sound_at(clawslicesound, victim->coords, 128);
3317 victim->DoBloodBig(2 / victim->armorhigh, 170);
3321 relative = victim->coords - oldcoords;
3323 Normalise(&relative);
3324 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3325 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3327 victim->jointVel(abdomen) += relative * damagemult * 200;
3328 victim->Puff(abdomen);
3329 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3331 award_bonus(id, Reversal);
3334 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3335 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3336 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3337 takeWeapon(victim->weaponids[victim->weaponactive]);
3338 victim->num_weapons--;
3339 if (victim->num_weapons > 0) {
3340 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3342 victim->weaponactive = -1;
3347 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3355 emit_sound_at(whooshhitsound, victim->coords, 128.);
3358 relative = victim->coords - oldcoords;
3360 Normalise(&relative);
3361 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3362 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3364 victim->jointVel(abdomen) += relative * damagemult * 200;
3366 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3369 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3378 award_bonus(id, staffreversebonus);
3380 if (!Tutorial::active) {
3381 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3384 award_bonus(id, staffreversebonus); // Huh, again?
3387 relative = victim->coords - oldcoords;
3389 Normalise(&relative);
3390 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3391 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3393 victim->jointVel(abdomen) += relative * damagemult * 200;
3395 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3398 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3404 Normalise(&relative);
3406 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3407 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3409 victim->jointVel(lefthand) *= .1;
3410 victim->jointVel(leftwrist) *= .2;
3411 victim->jointVel(leftelbow) *= .5;
3412 victim->jointVel(leftshoulder) *= .7;
3413 victim->jointVel(righthand) *= .1;
3414 victim->jointVel(rightwrist) *= .2;
3415 victim->jointVel(rightelbow) *= .5;
3416 victim->jointVel(rightshoulder) *= .7;
3418 victim->Puff(abdomen);
3419 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3421 award_bonus(id, Reversal);
3425 if (weaponactive != -1 || creature == wolftype)
3427 if (creature == rabbittype && weaponactive != -1)
3428 if (weapons[weaponids[0]].getType() == staff)
3431 if (weaponactive != -1) {
3432 victim->DoBloodBig(2 / victim->armorhigh, 225);
3433 emit_sound_at(knifeslicesound, victim->coords);
3434 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3435 weapons[weaponids[weaponactive]].bloody = 1;
3436 weapons[weaponids[weaponactive]].blooddrip += 3;
3438 if (weaponactive == -1 && creature == wolftype) {
3439 emit_sound_at(clawslicesound, victim->coords, 128.);
3441 victim->DoBloodBig(2 / victim->armorhigh, 175);
3448 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3454 Normalise(&relative);
3456 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3457 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3459 victim->jointVel(lefthand) *= .1 - 1;
3460 victim->jointVel(leftwrist) *= .2 - 1;
3461 victim->jointVel(leftelbow) *= .5 - 1;
3462 victim->jointVel(leftshoulder) *= .7 - 1;
3463 victim->jointVel(righthand) *= .1 - 1;
3464 victim->jointVel(rightwrist) *= .2 - 1;
3465 victim->jointVel(rightelbow) *= .5 - 1;
3466 victim->jointVel(rightshoulder) *= .7 - 1;
3468 award_bonus(id, swordreversebonus);
3471 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3479 if (!Tutorial::active) {
3480 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3484 relative = victim->coords - oldcoords;
3486 Normalise(&relative);
3487 relative = DoRotation(relative, 0, -90, 0);
3488 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3489 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3491 victim->jointVel(abdomen) += relative * damagemult * 200;
3492 victim->Puff(abdomen);
3493 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3495 award_bonus(id, Reversal);
3498 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3501 victim->skeleton.spinny = 0;
3503 relative = facing * -1;
3505 Normalise(&relative);
3506 if (victim->id == 0)
3508 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3509 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3511 victim->damage = victim->damagetolerance;
3512 victim->permanentdamage = victim->damagetolerance - 1;
3515 if (weaponactive != -1 || creature == wolftype)
3517 if (creature == rabbittype && weaponactive != -1)
3518 if (weapons[weaponids[0]].getType() == staff)
3521 if (weaponactive != -1) {
3522 victim->DoBloodBig(200, 225);
3523 emit_sound_at(knifeslicesound, victim->coords);
3525 weapons[weaponids[weaponactive]].bloody = 2;
3526 weapons[weaponids[weaponactive]].blooddrip += 5;
3529 if (creature == wolftype && weaponactive == -1) {
3530 emit_sound_at(clawslicesound, victim->coords, 128.);
3532 victim->DoBloodBig(2, 175);
3535 award_bonus(id, spinecrusher);
3538 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3539 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3541 if (animTarget == knifefollowanim)
3542 victim->DoBloodBig(200, 210);
3543 if (animTarget == knifesneakattackanim) {
3544 XYZ footvel, footpoint;
3546 footpoint = weapons[weaponids[0]].tippoint;
3548 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3549 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3550 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3551 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3552 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3553 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3554 victim->DoBloodBig(200, 195);
3555 award_bonus(id, tracheotomy);
3557 if (animTarget == knifefollowanim) {
3558 award_bonus(id, Stabbonus);
3559 XYZ footvel, footpoint;
3561 footpoint = weapons[weaponids[0]].tippoint;
3563 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3564 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3565 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3566 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3567 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3568 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3571 victim->bloodloss += 10000;
3572 victim->velocity = 0;
3573 emit_sound_at(fleshstabsound, victim->coords);
3575 weapons[weaponids[weaponactive]].bloody = 2;
3576 weapons[weaponids[weaponactive]].blooddrip += 5;
3580 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3582 victim->velocity = 0;
3583 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3584 victim->skeleton.joints[i].velocity = 0;
3586 if (animTarget == knifefollowanim) {
3588 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3589 victim->skeleton.joints[i].velocity = 0;
3592 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3593 emit_sound_at(fleshstabremovesound, victim->coords);
3595 weapons[weaponids[weaponactive]].bloody = 2;
3596 weapons[weaponids[weaponactive]].blooddrip += 5;
3598 XYZ footvel, footpoint;
3600 footpoint = weapons[weaponids[0]].tippoint;
3602 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3603 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3604 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3605 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3606 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3607 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3611 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3612 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3613 award_bonus(id, backstab);
3617 XYZ footvel, footpoint;
3619 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3621 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3622 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3623 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3624 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3625 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3626 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3627 victim->DoBloodBig(200, 180);
3628 victim->DoBloodBig(200, 215);
3629 victim->bloodloss += 10000;
3630 victim->velocity = 0;
3631 emit_sound_at(fleshstabsound, victim->coords);
3633 weapons[weaponids[weaponactive]].bloody = 2;
3634 weapons[weaponids[weaponactive]].blooddrip += 5;
3638 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3640 victim->velocity = 0;
3641 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3642 victim->skeleton.joints[i].velocity = 0;
3644 if (weaponactive != -1) {
3645 emit_sound_at(fleshstabremovesound, victim->coords);
3647 weapons[weaponids[weaponactive]].bloody = 2;
3648 weapons[weaponids[weaponactive]].blooddrip += 5;
3650 XYZ footvel, footpoint;
3652 footpoint = weapons[weaponids[0]].tippoint;
3654 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3655 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3656 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3657 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3658 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3659 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3663 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3671 if (weaponactive == -1) {
3672 if (!Tutorial::active) {
3673 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3678 if (weaponactive != -1 || creature == wolftype)
3680 if (creature == rabbittype && weaponactive != -1)
3681 if (weapons[weaponids[0]].getType() == staff)
3684 if (weaponactive != -1) {
3685 victim->DoBloodBig(2 / victim->armorhead, 225);
3686 emit_sound_at(knifeslicesound, victim->coords);
3687 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3688 weapons[weaponids[weaponactive]].bloody = 1;
3689 weapons[weaponids[weaponactive]].blooddrip += 3;
3691 if (weaponactive == -1 && creature == wolftype) {
3692 emit_sound_at(clawslicesound, victim->coords, 128.);
3694 victim->DoBloodBig(2 / victim->armorhead, 175);
3698 award_bonus(id, Reversal);
3703 relative = facing * -1;
3705 Normalise(&relative);
3706 relative = DoRotation(relative, 0, 90, 0);
3708 Normalise(&relative);
3709 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3710 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3712 victim->jointVel(head) += relative * damagemult * 200;
3713 if (victim->damage < victim->damagetolerance - 100)
3714 victim->velocity = relative * 200;
3715 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3716 victim->velocity = 0;
3719 if (animTarget == sweepreversalanim && ((Animation::animations[animTarget].frames[frameCurrent].label == 9 && victim->damage < victim->damagetolerance) || (Animation::animations[animTarget].frames[frameCurrent].label == 7 && victim->damage > victim->damagetolerance))) {
3723 relative = facing * -1;
3725 Normalise(&relative);
3726 relative = DoRotation(relative, 0, 90, 0);
3728 Normalise(&relative);
3729 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3730 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3732 victim->jointVel(head) += relative * damagemult * 200;
3735 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3736 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3737 award_bonus(id, reverseko);
3743 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3746 animTarget = getIdle();
3747 FootLand(leftfoot, 1);
3748 FootLand(rightfoot, 1);
3750 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3751 animTarget = rollanim;
3753 emit_sound_at(movewhooshsound, coords, 128.);
3755 if (animCurrent == staggerbackhighanim) {
3756 animTarget = getIdle();
3758 if (animCurrent == staggerbackhardanim) {
3759 animTarget = getIdle();
3761 if (animCurrent == removeknifeanim) {
3762 animTarget = getIdle();
3764 if (animCurrent == crouchremoveknifeanim) {
3765 animTarget = getCrouch();
3767 if (animCurrent == backhandspringanim) {
3768 animTarget = getIdle();
3770 if (animCurrent == dodgebackanim) {
3771 animTarget = getIdle();
3773 if (animCurrent == drawleftanim) {
3774 animTarget = getIdle();
3776 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3777 animTarget = getIdle();
3778 if (animCurrent == crouchdrawrightanim) {
3779 animTarget = getCrouch();
3781 if (weaponactive == -1)
3783 else if (weaponactive == 0) {
3785 if (num_weapons == 2) {
3787 buffer = weaponids[0];
3788 weaponids[0] = weaponids[1];
3789 weaponids[1] = buffer;
3793 if (weaponactive == -1) {
3794 emit_sound_at(knifesheathesound, coords, 128.);
3796 if (weaponactive != -1) {
3797 emit_sound_at(knifedrawsound, coords, 128.);
3800 if (animCurrent == rollanim) {
3801 animTarget = getCrouch();
3802 FootLand(leftfoot, 1);
3803 FootLand(rightfoot, 1);
3806 if (animTarget == walljumprightkickanim) {
3809 if (animTarget == walljumpleftkickanim) {
3812 animTarget = jumpdownanim;
3814 if (animCurrent == climbanim) {
3815 animTarget = getCrouch();
3817 coords += facing * .1;
3818 if (!isnormal(coords.x))
3828 if (animTarget == rabbitkickreversalanim) {
3829 animTarget = getCrouch();
3832 if (animTarget == jumpreversalanim) {
3833 animTarget = getCrouch();
3836 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3837 if (attackkeydown && animTarget != walljumpfrontanim) {
3839 float closestdist = -1;
3841 if (Person::players.size() > 1)
3842 for (unsigned i = 0; i < Person::players.size(); i++) {
3843 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3844 distance = distsq(&Person::players[i]->coords, &coords);
3845 if (closestdist == -1 || distance < closestdist) {
3846 closestdist = distance;
3851 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3852 victim = Person::players[closest];
3853 animTarget = walljumprightkickanim;
3855 XYZ rotatetarget = victim->coords - coords;
3856 Normalise(&rotatetarget);
3857 yaw = -asin(0 - rotatetarget.x);
3859 if (rotatetarget.z < 0)
3861 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3862 velocity = (victim->coords - coords) * 4;
3867 if (animTarget == walljumpbackanim) {
3868 animTarget = backflipanim;
3870 velocity = facing * -8;
3873 resume_stream(whooshsound);
3875 if (animTarget == walljumprightanim) {
3876 animTarget = rightflipanim;
3880 velocity = DoRotation(facing, 0, 30, 0) * -8;
3883 if (animTarget == walljumpfrontanim) {
3884 animTarget = frontflipanim;
3888 velocity = facing * 8;
3892 resume_stream(whooshsound);
3894 if (animTarget == walljumpleftanim) {
3895 if (attackkeydown) {
3897 float closestdist = -1;
3899 if (Person::players.size() > 1)
3900 for (unsigned i = 0; i < Person::players.size(); i++) {
3901 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3902 distance = distsq(&Person::players[i]->coords, &coords);
3903 if (closestdist == -1 || distance < closestdist) {
3904 closestdist = distance;
3909 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3910 victim = Person::players[closest];
3911 animTarget = walljumpleftkickanim;
3913 XYZ rotatetarget = victim->coords - coords;
3914 Normalise(&rotatetarget);
3915 yaw = -asin(0 - rotatetarget.x);
3917 if (rotatetarget.z < 0)
3919 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3920 velocity = (victim->coords - coords) * 4;
3925 if (animTarget != walljumpleftkickanim) {
3926 animTarget = leftflipanim;
3930 velocity = DoRotation(facing, 0, -30, 0) * -8;
3934 resume_stream(whooshsound);
3936 if (animTarget == sneakattackanim) {
3937 animCurrent = getCrouch();
3938 animTarget = getCrouch();
3945 transspeed = 1000000;
3946 targetheadyaw += 180;
3947 coords -= facing * .7;
3949 coords.y = terrain.getHeight(coords.x, coords.z);
3953 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3954 animTarget = getIdle();
3957 coords.y = terrain.getHeight(coords.x, coords.z);
3961 if (animCurrent == knifefollowanim) {
3962 animTarget = getIdle();
3965 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3966 float ycoords = oldcoords.y;
3967 animTarget = getStop();
3972 transspeed = 1000000;
3973 targetheadyaw += 180;
3974 if (!isnormal(coords.x))
3976 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3977 oldcoords = coords + facing * .5;
3978 else if (animCurrent == sweepreversalanim)
3979 oldcoords = coords + facing * 1.1;
3980 else if (animCurrent == upunchreversalanim) {
3981 oldcoords = coords + facing * 1.5;
3984 targetheadyaw += 180;
3987 } else if (animCurrent == knifeslashreversalanim) {
3988 oldcoords = coords + facing * .5;
3991 targetheadyaw += 90;
3994 } else if (animCurrent == staffspinhitreversalanim) {
3997 targetheadyaw += 180;
4002 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4004 oldcoords.y = ycoords;
4005 currentoffset = coords - oldcoords;
4011 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4016 if (Animation::animations[animTarget].attack == reversed) {
4018 if (animTarget == sweepreversedanim)
4020 animTarget = backhandspringanim;
4022 emit_sound_at(landsound, coords, 128);
4024 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4025 animTarget = rollanim;
4028 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4029 coords.y = oldcoords.y;
4031 if (animCurrent == knifeslashreversedanim) {
4032 animTarget = rollanim;
4037 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4038 coords.y = oldcoords.y;
4042 animTarget = jumpdownanim;
4045 animTarget = getIdle();
4047 animTarget = getIdle();
4048 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4049 animTarget = getIdle();
4051 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4052 coords.y = oldcoords.y;
4053 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4054 targetoffset.y = coords.y;
4056 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4057 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4058 currentoffset.y -= (coords.y - targetoffset.y);
4059 coords.y = targetoffset.y;
4061 normalsupdatedelay = 0;
4063 if (animCurrent == upunchanim) {
4064 animTarget = getStop();
4065 normalsupdatedelay = 0;
4068 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4072 if (num_weapons > 0)
4073 if (weapons[0].getType() == staff)
4079 rabbitkickragdoll = 1;
4081 if (animCurrent == rabbitkickreversedanim) {
4087 skeleton.spinny = 0;
4088 SolidHitBonus(!id); // FIXME: tricky id
4092 animTarget = rollanim;
4095 pause_sound(whooshsound);
4099 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4103 skeleton.spinny = 0;
4105 if (animCurrent == jumpreversedanim) {
4111 skeleton.spinny = 0;
4112 SolidHitBonus(!id); // FIXME: tricky id
4116 animTarget = rollanim;
4117 coords += facing * 2;
4119 pause_sound(whooshsound);
4124 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) {
4125 animTarget = getupfromfrontanim;
4127 } else if (Animation::animations[animCurrent].attack == normalattack) {
4128 animTarget = getIdle();
4131 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4132 animTarget = blockhighleftstrikeanim;
4134 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4135 animTarget = getIdle();
4138 if (animCurrent == spinkickanim && victim->skeleton.free) {
4139 if (creature == rabbittype)
4140 animTarget = fightidleanim;
4145 if (isIdle() && !wasIdle())
4146 normalsupdatedelay = 0;
4148 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4149 animTarget = jumpdownanim;
4152 if (!skeleton.free) {
4154 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4155 if (!isRun() || !wasRun()) {
4156 if (targetFrame().speed > currentFrame().speed)
4157 target += multiplier * targetFrame().speed * speed * 2;
4158 if (targetFrame().speed <= currentFrame().speed)
4159 target += multiplier * currentFrame().speed * speed * 2;
4161 if (isRun() && wasRun()) {
4163 tempspeed = velspeed;
4164 if (tempspeed < 10 * speedmult)
4165 tempspeed = 10 * speedmult;
4166 /* FIXME - mixed of target and current here, is that intended? */
4167 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4169 } else if (transspeed)
4170 target += multiplier * transspeed * speed * 2;
4172 if (!isRun() || !wasRun()) {
4173 if (targetFrame().speed > currentFrame().speed)
4174 target += multiplier * targetFrame().speed * 2;
4175 if (targetFrame().speed <= currentFrame().speed)
4176 target += multiplier * currentFrame().speed * 2;
4180 if (animCurrent != animTarget)
4181 target = (target + oldtarget) / 2;
4184 frameCurrent = frameTarget;
4188 rot = targetrot * target;
4189 yaw += rot - oldrot;
4195 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4196 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4198 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4200 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4201 skeleton.joints[i].position = currentFrame().joints[i].position;
4204 skeleton.FindForwards();
4206 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4207 if (skeleton.muscles[i].visible) {
4208 skeleton.FindRotationMuscle(i, animTarget);
4211 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4212 if (skeleton.muscles[i].visible) {
4213 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4214 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4215 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4216 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4217 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4218 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4223 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4224 skeleton.joints[i].position = targetFrame().joints[i].position;
4227 skeleton.FindForwards();
4229 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4230 if (skeleton.muscles[i].visible) {
4231 skeleton.FindRotationMuscle(i, animTarget);
4234 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4235 if (skeleton.muscles[i].visible) {
4236 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4237 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4238 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4239 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4240 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4241 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4242 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4243 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4244 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4245 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4246 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4247 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4252 oldanimCurrent = animCurrent;
4253 oldanimTarget = animTarget;
4254 oldframeTarget = frameTarget;
4255 oldframeCurrent = frameCurrent;
4257 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4258 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4259 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4261 offset = currentoffset * (1 - target) + targetoffset * target;
4262 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4263 if (skeleton.muscles[i].visible) {
4264 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4265 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4266 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4271 if (isLanding() && landhard) {
4274 animTarget = getLandhard();
4287 void Person::DoStuff()
4289 static XYZ terrainnormal;
4290 static XYZ flatfacing;
4291 static XYZ flatvelocity;
4292 static float flatvelspeed;
4293 static int bloodsize;
4294 static int startx, starty, endx, endy;
4295 static GLubyte color;
4296 static XYZ bloodvel;
4298 onfiredelay -= multiplier;
4299 if (onfiredelay < 0 && onfire) {
4300 if (Random() % 2 == 0) {
4306 crouchkeydowntime += multiplier;
4308 crouchkeydowntime = 0;
4309 jumpkeydowntime += multiplier;
4310 if (!jumpkeydown && skeleton.free)
4311 jumpkeydowntime = 0;
4313 if (hostile || damage > 0 || bloodloss > 0)
4316 if (isIdle() || isRun())
4319 if (num_weapons == 1 && weaponactive != -1)
4323 blooddimamount -= multiplier * .3;
4324 speechdelay -= multiplier;
4325 texupdatedelay -= multiplier;
4326 interestdelay -= multiplier;
4327 flamedelay -= multiplier;
4328 parriedrecently -= multiplier;
4330 victim = this->shared_from_this();
4335 speed = 1.1 * speedmult;
4337 speed = 1.0 * speedmult;
4339 rabbitkickragdoll = 0;
4343 if (id != 0 && (creature == rabbittype || difficulty != 2))
4345 if (id != 0 && creature == wolftype && difficulty == 2) {
4347 if (aitype != passivetype) {
4349 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) {
4355 if (animTarget == wolfrunninganim && !superruntoggle) {
4356 animTarget = getRun();
4360 if (weaponactive == -1 && num_weapons > 0) {
4361 if (weapons[weaponids[0]].getType() == staff) {
4367 burnt += multiplier;
4371 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4373 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4379 vel[0] = velocity.x;
4380 vel[1] = velocity.y;
4381 vel[2] = velocity.z;
4384 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4385 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4389 while (flamedelay < 0 && onfire) {
4391 int howmany = fabs(Random() % (skeleton.joints.size()));
4392 if (skeleton.free) {
4393 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4394 flatfacing = skeleton.joints[howmany].position * scale + coords;
4396 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4397 flatvelocity = (coords - oldcoords) / multiplier / 2;
4399 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4402 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4404 int howmany = fabs(Random() % (skeleton.joints.size()));
4405 if (skeleton.free) {
4406 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4407 flatfacing = skeleton.joints[howmany].position * scale + coords;
4409 flatvelocity = (coords - oldcoords) / multiplier / 2;
4410 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4412 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4416 bleeding -= multiplier * .3;
4417 if (bloodtoggle == 2) {
4418 skeleton.drawmodel.textureptr.bind();
4419 if ((bleeding <= 0) && (detail != 2))
4424 if (neckspurtamount > 0) {
4425 neckspurtamount -= multiplier;
4426 neckspurtdelay -= multiplier * 3;
4427 neckspurtparticledelay -= multiplier * 3;
4428 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4431 if (skeleton.free) {
4432 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4433 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4434 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4436 bloodvel.z = 5 * neckspurtamount;
4437 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4438 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4439 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4441 neckspurtparticledelay = .05;
4443 if (neckspurtdelay < 0) {
4448 if (deathbleeding > 0 && dead != 2) {
4449 if (deathbleeding < 5)
4450 bleeddelay -= deathbleeding * multiplier / 4;
4452 bleeddelay -= 5 * multiplier / 4;
4453 if (bleeddelay < 0 && bloodtoggle) {
4458 if (skeleton.free) {
4459 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4460 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4462 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4463 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4467 bloodloss += deathbleeding * multiplier * 80;
4468 deathbleeding -= multiplier * 1.6;
4469 if (deathbleeding < 0)
4471 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4472 if (weaponactive != -1) {
4473 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4474 weapons[weaponids[0]].velocity.x += .01;
4477 weaponids[0] = weaponids[num_weapons];
4478 if (weaponstuck == num_weapons)
4482 for (unsigned i = 0; i < Person::players.size(); i++) {
4483 Person::players[i]->wentforweapon = 0;
4491 if (!dead && creature == wolftype) {
4492 award_bonus(0, Wolfbonus);
4495 if (animTarget == knifefollowedanim && !skeleton.free) {
4496 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4497 skeleton.joints[i].velocity = 0;
4498 skeleton.joints[i].velocity.y = -2;
4501 if (id != 0 && unconscioustime > .1) {
4509 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4510 texupdatedelay = .12;
4512 bloodsize = 5 - realtexdetail;
4516 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4517 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4518 endx = startx + bloodsize;
4519 endy = starty + bloodsize;
4529 if (endx > skeleton.skinsize - 1) {
4530 endx = skeleton.skinsize - 1;
4533 if (endy > skeleton.skinsize - 1) {
4534 endy = skeleton.skinsize - 1;
4542 for (int i = startx; i < endx; i++) {
4543 for (int j = starty; j < endy; j++) {
4544 if (Random() % 2 == 0) {
4545 color = Random() % 85 + 170;
4546 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4547 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4548 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4549 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4554 skeleton.drawmodel.textureptr.bind();
4558 if (skeleton.free) {
4559 bleedx += 4 * direction / realtexdetail;
4561 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4563 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4565 bleedy -= 4 / realtexdetail;
4567 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4569 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4573 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4574 righthandmorphness = targetrighthandmorphness;
4575 righthandmorphstart = righthandmorphend;
4576 } else if (righthandmorphness > targetrighthandmorphness) {
4577 righthandmorphness -= multiplier * 4;
4578 } else if (righthandmorphness < targetrighthandmorphness) {
4579 righthandmorphness += multiplier * 4;
4582 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4583 lefthandmorphness = targetlefthandmorphness;
4584 lefthandmorphstart = lefthandmorphend;
4585 } else if (lefthandmorphness > targetlefthandmorphness) {
4586 lefthandmorphness -= multiplier * 4;
4587 } else if (lefthandmorphness < targetlefthandmorphness) {
4588 lefthandmorphness += multiplier * 4;
4591 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4592 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4593 tailmorphness = targettailmorphness;
4594 tailmorphstart = tailmorphend;
4595 } else if (tailmorphness > targettailmorphness) {
4596 tailmorphness -= multiplier * 10;
4597 } else if (tailmorphness < targettailmorphness) {
4598 tailmorphness += multiplier * 10;
4602 if (creature == wolftype) {
4603 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4604 tailmorphness = targettailmorphness;
4605 tailmorphstart = tailmorphend;
4606 } else if (tailmorphness > targettailmorphness) {
4607 tailmorphness -= multiplier * 2;
4608 } else if (tailmorphness < targettailmorphness) {
4609 tailmorphness += multiplier * 2;
4613 if (headmorphend == 3 || headmorphstart == 3) {
4614 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4615 headmorphness = targetheadmorphness;
4616 headmorphstart = headmorphend;
4617 } else if (headmorphness > targetheadmorphness) {
4618 headmorphness -= multiplier * 7;
4619 } else if (headmorphness < targetheadmorphness) {
4620 headmorphness += multiplier * 7;
4622 } else if (headmorphend == 5 || headmorphstart == 5) {
4623 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4624 headmorphness = targetheadmorphness;
4625 headmorphstart = headmorphend;
4626 } else if (headmorphness > targetheadmorphness) {
4627 headmorphness -= multiplier * 10;
4628 } else if (headmorphness < targetheadmorphness) {
4629 headmorphness += multiplier * 10;
4632 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4633 headmorphness = targetheadmorphness;
4634 headmorphstart = headmorphend;
4635 } else if (headmorphness > targetheadmorphness) {
4636 headmorphness -= multiplier * 4;
4637 } else if (headmorphness < targetheadmorphness) {
4638 headmorphness += multiplier * 4;
4642 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4643 chestmorphness = targetchestmorphness;
4644 chestmorphstart = chestmorphend;
4645 } else if (chestmorphness > targetchestmorphness) {
4646 chestmorphness -= multiplier;
4647 } else if (chestmorphness < targetchestmorphness) {
4648 chestmorphness += multiplier;
4651 if (dead != 2 && howactive <= typesleeping) {
4652 if (chestmorphstart == 0 && chestmorphend == 0) {
4654 targetchestmorphness = 1;
4657 if (chestmorphstart != 0 && chestmorphend != 0) {
4659 targetchestmorphness = 1;
4661 if (environment == snowyenvironment) {
4664 if (skeleton.free) {
4665 footvel = skeleton.specialforward[0] * -1;
4666 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4668 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4669 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4671 if (animTarget == sleepanim)
4672 footvel = DoRotation(footvel, 0, 90, 0);
4673 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4677 if (!dead && howactive < typesleeping) {
4678 blinkdelay -= multiplier * 2;
4679 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4681 targetheadmorphness = 1;
4683 blinkdelay = (float)(abs(Random() % 40)) / 5;
4685 if (headmorphstart == 3 && headmorphend == 3) {
4687 targetheadmorphness = 1;
4692 twitchdelay -= multiplier * 1.5;
4693 if (animTarget != hurtidleanim) {
4694 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4696 targetheadmorphness = 1;
4698 twitchdelay = (float)(abs(Random() % 40)) / 5;
4700 if (headmorphstart == 5 && headmorphend == 5) {
4702 targetheadmorphness = 1;
4706 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4707 twitchdelay3 -= multiplier * 1;
4708 if (Random() % 2 == 0) {
4709 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4710 righthandmorphness = 0;
4711 targetrighthandmorphness = 1;
4712 righthandmorphend = 1;
4713 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4715 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4716 righthandmorphness = 0;
4717 targetrighthandmorphness = 1;
4718 righthandmorphend = 0;
4721 if (Random() % 2 == 0) {
4722 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4723 lefthandmorphness = 0;
4724 targetlefthandmorphness = 1;
4725 lefthandmorphend = 1;
4726 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4728 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4729 lefthandmorphness = 0;
4730 targetlefthandmorphness = 1;
4731 lefthandmorphend = 0;
4737 if (creature == rabbittype) {
4738 if (howactive < typesleeping)
4739 twitchdelay2 -= multiplier * 1.5;
4741 twitchdelay2 -= multiplier * 0.5;
4742 if (howactive <= typesleeping) {
4743 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4745 targettailmorphness = 1;
4747 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4749 if (tailmorphstart == 1 && tailmorphend == 1) {
4751 targettailmorphness = 1;
4754 if (tailmorphstart == 2 && tailmorphend == 2) {
4756 targettailmorphness = 1;
4763 if (creature == wolftype) {
4764 twitchdelay2 -= multiplier * 1.5;
4765 if (tailmorphend != 0)
4766 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4768 targettailmorphness = 1;
4772 if (tailmorphend != 5)
4773 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4775 targettailmorphness = 1;
4779 if (twitchdelay2 <= 0) {
4780 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4782 targettailmorphness = 1;
4785 if (tailmorphstart == 1 && tailmorphend == 1) {
4787 targettailmorphness = 1;
4790 if (tailmorphstart == 2 && tailmorphend == 2) {
4792 targettailmorphness = 1;
4795 if (tailmorphstart == 3 && tailmorphend == 3) {
4797 targettailmorphness = 1;
4800 if (tailmorphstart == 4 && tailmorphend == 4) {
4802 targettailmorphness = 1;
4809 unconscioustime = 0;
4812 if (dead == 1 || howactive == typesleeping) {
4813 unconscioustime += multiplier;
4814 //If unconscious, close eyes and mouth
4815 if (righthandmorphend != 0)
4816 righthandmorphness = 0;
4817 righthandmorphend = 0;
4818 targetrighthandmorphness = 1;
4820 if (lefthandmorphend != 0)
4821 lefthandmorphness = 0;
4822 lefthandmorphend = 0;
4823 targetlefthandmorphness = 1;
4825 if (headmorphend != 3 && headmorphend != 5)
4828 targetheadmorphness = 1;
4832 if (howactive > typesleeping) {
4835 if (bloodtoggle && !bled) {
4836 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4837 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
4838 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4839 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4843 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4849 if (dead == 2 || howactive > typesleeping) {
4850 //If dead, open mouth and hands
4851 if (righthandmorphend != 0)
4852 righthandmorphness = 0;
4853 righthandmorphend = 0;
4854 targetrighthandmorphness = 1;
4856 if (lefthandmorphend != 0)
4857 lefthandmorphness = 0;
4858 lefthandmorphend = 0;
4859 targetlefthandmorphness = 1;
4861 if (headmorphend != 2)
4864 targetheadmorphness = 1;
4867 if (stunned > 0 && !dead && headmorphend != 2) {
4868 if (headmorphend != 4)
4871 targetheadmorphness = 1;
4874 if (damage > damagetolerance && !dead) {
4877 unconscioustime = 0;
4879 if (creature == wolftype) {
4880 award_bonus(0, Wolfbonus);
4885 if (weaponactive != -1) {
4886 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4887 weapons[weaponids[0]].velocity.x += .01;
4890 weaponids[0] = weaponids[num_weapons];
4891 if (weaponstuck == num_weapons)
4895 for (unsigned i = 0; i < Person::players.size(); i++) {
4896 Person::players[i]->wentforweapon = 0;
4902 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4911 damage -= multiplier * 13;
4912 permanentdamage -= multiplier * 4;
4913 if (isIdle() || isCrouch()) {
4914 permanentdamage -= multiplier * 4;
4919 if (permanentdamage < 0)
4920 permanentdamage = 0;
4921 if (superpermanentdamage < 0)
4922 superpermanentdamage = 0;
4923 if (permanentdamage < superpermanentdamage) {
4924 permanentdamage = superpermanentdamage;
4926 if (damage < permanentdamage) {
4927 damage = permanentdamage;
4929 if (dead == 1 && damage < damagetolerance) {
4933 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4934 skeleton.joints[i].velocity = 0;
4937 if (permanentdamage > damagetolerance && dead != 2) {
4940 if (weaponactive != -1) {
4941 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4942 weapons[weaponids[0]].velocity.x += .01;
4945 weaponids[0] = weaponids[num_weapons];
4946 if (weaponstuck == num_weapons)
4950 for (unsigned i = 0; i < Person::players.size(); i++) {
4951 Person::players[i]->wentforweapon = 0;
4957 if (!dead && creature == wolftype) {
4958 award_bonus(0, Wolfbonus);
4961 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4962 award_bonus(id, touchofdeath);
4963 if (id != 0 && unconscioustime > .1) {
4971 emit_sound_at(breaksound, coords);
4974 if (skeleton.free == 1) {
4976 pause_sound(whooshsound);
4979 //If knocked over, open hands and close mouth
4980 if (righthandmorphend != 0)
4981 righthandmorphness = 0;
4982 righthandmorphend = 0;
4983 targetrighthandmorphness = 1;
4985 if (lefthandmorphend != 0)
4986 lefthandmorphness = 0;
4987 lefthandmorphend = 0;
4988 targetlefthandmorphness = 1;
4990 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4991 if (headmorphend != 0)
4994 targetheadmorphness = 1;
4998 skeleton.DoGravity(&scale);
5000 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5001 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
5002 award_bonus(id, deepimpact);
5003 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5007 if (!skeleton.joints.empty()) {
5008 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5009 average += skeleton.joints[j].position;
5011 average /= skeleton.joints.size();
5012 coords += average * scale;
5013 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5014 skeleton.joints[j].position -= average;
5016 average /= multiplier;
5020 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5021 velocity += skeleton.joints[i].velocity * scale;
5023 velocity /= skeleton.joints.size();
5025 if (!isnormal(velocity.x) && velocity.x) {
5029 if (findLength(&average) < 10 && dead && skeleton.free) {
5030 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5031 if (skeleton.longdead > 2000) {
5032 if (skeleton.longdead > 6000) {
5034 pause_sound(whooshsound);
5039 if (dead == 2 && bloodloss < damagetolerance) {
5041 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5043 if (bloodtoggle && !bled) {
5044 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5045 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5046 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5047 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5048 float size = .2 * 1.2;
5051 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5056 if (dead == 2 && bloodloss >= damagetolerance) {
5058 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5061 if (bloodtoggle && !bled) {
5062 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5063 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5064 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5065 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5069 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5077 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5078 bool canrecover = 1;
5079 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5080 startpoint = coords;
5083 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5085 if (velocity.y < -30)
5087 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5088 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5089 colviewer = startpoint;
5090 coltarget = endpoint;
5091 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5100 terrainnormal = jointPos(groin) - jointPos(abdomen);
5101 if (joint(groin).locked && joint(abdomen).locked) {
5102 terrainnormal = jointPos(groin) - jointPos(abdomen);
5103 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5105 if (joint(abdomen).locked && joint(neck).locked) {
5106 terrainnormal = jointPos(abdomen) - jointPos(neck);
5107 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5109 if (joint(groin).locked && joint(neck).locked) {
5110 terrainnormal = jointPos(groin) - jointPos(neck);
5111 middle = (jointPos(groin) + jointPos(neck)) / 2;
5113 Normalise(&terrainnormal);
5115 targetyaw = -asin(0 - terrainnormal.x);
5116 targetyaw *= 360 / 6.28;
5117 if (terrainnormal.z < 0)
5118 targetyaw = 180 - targetyaw;
5122 animTarget = flipanim;
5123 crouchtogglekeydown = 1;
5128 animCurrent = tempanim;
5132 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5133 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5134 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5139 if (findLength(&average) < 10 && !dead && skeleton.free) {
5140 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5141 if (skeleton.longdead > (damage + 500) * 1.5) {
5143 pause_sound(whooshsound);
5149 terrainnormal = jointPos(groin) - jointPos(abdomen);
5150 if (joint(groin).locked && joint(abdomen).locked) {
5151 terrainnormal = jointPos(groin) - jointPos(abdomen);
5152 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5154 if (joint(abdomen).locked && joint(neck).locked) {
5155 terrainnormal = jointPos(abdomen) - jointPos(neck);
5156 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5158 if (joint(groin).locked && joint(neck).locked) {
5159 terrainnormal = jointPos(groin) - jointPos(neck);
5160 middle = (jointPos(groin) + jointPos(neck)) / 2;
5162 Normalise(&terrainnormal);
5164 targetyaw = -asin(0 - terrainnormal.x);
5165 targetyaw *= 360 / 6.28;
5166 if (terrainnormal.z < 0)
5167 targetyaw = 180 - targetyaw;
5170 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5173 if (skeleton.forward.y < 0) {
5174 animTarget = getupfrombackanim;
5178 if (skeleton.forward.y > -.3) {
5179 animTarget = getupfromfrontanim;
5187 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5188 animTarget = rollanim;
5189 targetyaw = lookyaw;
5206 if ( !leftkeydown && !rightkeydown)
5213 if (abs(targettilt2) > 50)
5215 animCurrent = tempanim;
5218 tilt2 = targettilt2;
5220 if (middle.y > 0 && animTarget != rollanim)
5221 targetoffset.y = middle.y + 1;
5223 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5224 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5225 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5232 if (num_weapons > 0)
5233 if (weapons[0].getType() == staff)
5235 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5236 if (velocity.y > -30) {
5238 tempvelocity = velocity;
5239 Normalise(&tempvelocity);
5240 targetyaw = -asin(0 - tempvelocity.x);
5241 targetyaw *= 360 / 6.28;
5243 targetyaw = 180 - targetyaw;
5247 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5248 animTarget = rollanim;
5251 animTarget = backhandspringanim;
5257 emit_sound_at(movewhooshsound, coords, 128.);
5259 animCurrent = animTarget;
5260 frameCurrent = frameTarget - 1;
5272 if (skeleton.freefall == 0)
5277 if (aitype != passivetype || skeleton.free == 1)
5278 if (findLengthfast(&velocity) > .1)
5279 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5280 if (Object::objects[i]->type == firetype)
5281 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) {
5283 if (!Object::objects[i]->onfire) {
5284 emit_sound_at(firestartsound, Object::objects[i]->position);
5286 Object::objects[i]->onfire = 1;
5289 if (Object::objects[i]->onfire) {
5294 if (Object::objects[i]->type == bushtype)
5295 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) {
5297 if (!Object::objects[i]->onfire) {
5298 emit_sound_at(firestartsound, Object::objects[i]->position);
5300 Object::objects[i]->onfire = 1;
5304 if (Object::objects[i]->onfire) {
5308 if (Object::objects[i]->messedwith <= 0) {
5312 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5315 addEnvSound(coords, 4 * findLength(&velocity));
5319 if (environment == grassyenvironment)
5320 howmany = findLength(&velocity) * 4;
5321 if (environment == snowyenvironment)
5322 howmany = findLength(&velocity) * 2;
5324 if (environment != desertenvironment)
5325 for (int j = 0; j < howmany; j++) {
5326 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5327 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5328 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5331 pos.x += float(abs(Random() % 100) - 50) / 200;
5332 pos.y += float(abs(Random() % 100) - 50) / 200;
5333 pos.z += float(abs(Random() % 100) - 50) / 200;
5334 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);
5335 Sprite::setLastSpriteSpecial(1);
5337 howmany = findLength(&velocity) * 4;
5339 if (environment == snowyenvironment)
5340 for (int j = 0; j < howmany; j++) {
5341 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5342 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5343 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5346 pos.x += float(abs(Random() % 100) - 50) / 200;
5347 pos.y += float(abs(Random() % 100) - 50) / 200;
5348 pos.z += float(abs(Random() % 100) - 50) / 200;
5349 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5350 Sprite::setLastSpriteSpecial(2);
5353 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5354 Object::objects[i]->roty += velocity.z * multiplier * 6;
5355 Object::objects[i]->messedwith = .5;
5358 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5359 if (Object::objects[i]->pitch == 0)
5362 tempcoord = coords - Object::objects[i]->position;
5363 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5364 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5365 tempcoord += Object::objects[i]->position;
5367 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) {
5368 if (Object::objects[i]->messedwith <= 0) {
5372 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5375 addEnvSound(coords, 4 * findLength(&velocity));
5379 if (environment == grassyenvironment)
5380 howmany = findLength(&velocity) * 4;
5381 if (environment == snowyenvironment)
5382 howmany = findLength(&velocity) * 2;
5384 if (environment != desertenvironment)
5385 for (int j = 0; j < howmany; j++) {
5386 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5387 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5388 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5390 pos += velocity * .1;
5392 pos.x += float(abs(Random() % 100) - 50) / 150;
5393 pos.y += float(abs(Random() % 100) - 50) / 150;
5394 pos.z += float(abs(Random() % 100) - 50) / 150;
5395 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);
5396 Sprite::setLastSpriteSpecial(1);
5398 howmany = findLength(&velocity) * 4;
5400 if (environment == snowyenvironment)
5401 for (int j = 0; j < howmany; j++) {
5402 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5403 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5404 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5406 pos += velocity * .1;
5408 pos.x += float(abs(Random() % 100) - 50) / 150;
5409 pos.y += float(abs(Random() % 100) - 50) / 150;
5410 pos.z += float(abs(Random() % 100) - 50) / 150;
5411 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5412 Sprite::setLastSpriteSpecial(2);
5415 Object::objects[i]->messedwith = .5;
5420 if (!skeleton.free) {
5423 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5426 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5428 if (Tutorial::active && id != 0)
5430 if (play && aitype != playercontrolled) {
5431 int whichsound = -1;
5432 if (speechdelay <= 0) {
5433 unsigned int i = abs(Random() % 4);
5434 if (creature == rabbittype) {
5436 whichsound = rabbitchitter;
5438 whichsound = rabbitchitter2;
5440 if (creature == wolftype) {
5442 whichsound = growlsound;
5444 whichsound = growl2sound;
5449 if (whichsound != -1) {
5450 emit_sound_at(whichsound, coords);
5454 if (animTarget == staggerbackhighanim)
5456 if (animTarget == staggerbackhardanim)
5458 staggerdelay -= multiplier;
5459 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5461 if (velocity.y < -30 && animTarget == jumpdownanim)
5463 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5464 animTarget = getIdle();
5468 weaponmissdelay -= multiplier;
5469 highreversaldelay -= multiplier;
5470 lowreversaldelay -= multiplier;
5471 lastcollide -= multiplier;
5472 skiddelay -= multiplier;
5473 if (!isnormal(velocity.x) && velocity.x) {
5476 if (!isnormal(targettilt) && targettilt) {
5479 if (!isnormal(targettilt2) && targettilt2) {
5482 if (!isnormal(targetyaw) && targetyaw) {
5486 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5487 //open hands and close mouth
5488 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5489 righthandmorphness = 0;
5490 righthandmorphend = 0;
5491 targetrighthandmorphness = 1;
5494 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5495 lefthandmorphness = 0;
5496 lefthandmorphend = 0;
5497 targetlefthandmorphness = 1;
5500 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5503 targetheadmorphness = 1;
5507 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) {
5508 //open hands and mouth
5509 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5510 righthandmorphness = 0;
5511 righthandmorphend = 0;
5512 targetrighthandmorphness = 1;
5515 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5516 lefthandmorphness = 0;
5517 lefthandmorphend = 0;
5518 targetlefthandmorphness = 1;
5521 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5524 targetheadmorphness = 1;
5528 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5529 //close hands and mouth
5530 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5531 righthandmorphness = 0;
5532 righthandmorphend = 1;
5533 targetrighthandmorphness = 1;
5536 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5537 lefthandmorphness = 0;
5538 lefthandmorphend = 1;
5539 targetlefthandmorphness = 1;
5542 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5545 targetheadmorphness = 1;
5549 if (animTarget == spinkickanim ||
5550 animTarget == staffspinhitreversalanim ||
5551 animTarget == staffspinhitreversedanim ||
5552 animTarget == staffhitreversalanim ||
5553 animTarget == staffhitreversedanim ||
5554 animTarget == hurtidleanim ||
5555 animTarget == winduppunchanim ||
5556 animTarget == swordslashreversalanim ||
5557 animTarget == swordslashreversedanim ||
5558 animTarget == knifeslashreversalanim ||
5559 animTarget == knifeslashreversedanim ||
5560 animTarget == knifethrowanim ||
5561 animTarget == knifefollowanim ||
5562 animTarget == knifefollowedanim ||
5563 animTarget == killanim ||
5564 animTarget == dropkickanim ||
5565 animTarget == upunchanim ||
5566 animTarget == knifeslashstartanim ||
5567 animTarget == swordslashanim ||
5568 animTarget == staffhitanim ||
5569 animTarget == staffspinhitanim ||
5570 animTarget == staffgroundsmashanim ||
5571 animTarget == spinkickreversalanim ||
5572 animTarget == sweepreversalanim ||
5573 animTarget == lowkickanim ||
5574 animTarget == sweepreversedanim ||
5575 animTarget == rabbitkickreversalanim ||
5576 animTarget == rabbitkickreversedanim ||
5577 animTarget == jumpreversalanim ||
5578 animTarget == jumpreversedanim) {
5579 //close hands and yell
5580 if (righthandmorphend != 1 &&
5581 righthandmorphness == targetrighthandmorphness) {
5582 righthandmorphness = 0;
5583 righthandmorphend = 1;
5584 targetrighthandmorphness = 1;
5587 if (lefthandmorphend != 1 &&
5588 lefthandmorphness == targetlefthandmorphness) {
5589 lefthandmorphness = 0;
5590 lefthandmorphend = 1;
5591 targetlefthandmorphness = 1;
5594 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5597 targetheadmorphness = 1;
5604 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5605 (victim->aitype != searchtype) && (aitype != passivetype) &&
5606 (aitype != searchtype) && (victim->id < Person::players.size())) {
5607 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5611 if (!dead && animTarget != hurtidleanim)
5612 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5613 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5616 targetheadmorphness = 1;
5620 if (weaponactive != -1) {
5621 if (weapons[weaponids[weaponactive]].getType() != staff) {
5622 righthandmorphstart = 1;
5623 righthandmorphend = 1;
5625 if (weapons[weaponids[weaponactive]].getType() == staff) {
5626 righthandmorphstart = 2;
5627 righthandmorphend = 2;
5629 targetrighthandmorphness = 1;
5632 terrainnormal = terrain.getNormal(coords.x, coords.z);
5634 if (Animation::animations[animTarget].attack != reversal) {
5635 if (!isnormal(coords.x))
5643 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5644 facing = flatfacing;
5645 ReflectVector(&facing, terrainnormal);
5649 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5651 targettilt2 = -facing.y * 20;
5656 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5658 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5659 flatvelocity = velocity;
5661 flatvelspeed = findLength(&flatvelocity);
5662 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5663 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5668 if (targettilt > 25)
5670 if (targettilt < -25)
5674 if (targettilt2 > 45)
5676 if (targettilt2 < -45)
5678 if (abs(tilt2 - targettilt2) < multiplier * 400)
5679 tilt2 = targettilt2;
5680 else if (tilt2 > targettilt2) {
5681 tilt2 -= multiplier * 400;
5682 } else if (tilt2 < targettilt2) {
5683 tilt2 += multiplier * 400;
5685 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5692 if (!isnormal(targettilt) && targettilt) {
5695 if (!isnormal(targettilt2) && targettilt2) {
5700 if (animTarget == rabbittackleanim) {
5701 velocity += facing * multiplier * speed * 700 * scale;
5702 velspeed = findLength(&velocity);
5703 if (velspeed > speed * 65 * scale) {
5704 velocity /= velspeed;
5705 velspeed = speed * 65 * scale;
5706 velocity *= velspeed;
5708 velocity.y += gravity * multiplier * 20;
5709 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5710 velspeed = findLength(&velocity);
5711 velocity = flatfacing * velspeed;
5713 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5714 if (isRun() || animTarget == rabbitkickanim) {
5715 velocity += facing * multiplier * speed * 700 * scale;
5716 velspeed = findLength(&velocity);
5717 if (velspeed > speed * 45 * scale) {
5718 velocity /= velspeed;
5719 velspeed = speed * 45 * scale;
5720 velocity *= velspeed;
5722 velocity.y += gravity * multiplier * 20;
5723 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5724 velspeed = findLength(&velocity);
5725 if (velspeed < speed * 30 * scale)
5726 velspeed = speed * 30 * scale;
5727 velocity = flatfacing * velspeed;
5729 } else if (isRun()) {
5730 velocity += facing * multiplier * speed * 700 * scale;
5731 velspeed = findLength(&velocity);
5732 if (creature == rabbittype) {
5733 if (velspeed > speed * 55 * scale) {
5734 velocity /= velspeed;
5735 velspeed = speed * 55 * scale;
5736 velocity *= velspeed;
5739 if (creature == wolftype) {
5740 if (velspeed > speed * 75 * scale) {
5741 velocity /= velspeed;
5742 velspeed = speed * 75 * scale;
5743 velocity *= velspeed;
5746 velocity.y += gravity * multiplier * 20;
5747 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5748 velspeed = findLength(&velocity);
5749 velocity = flatfacing * velspeed;
5752 if (animTarget == rollanim && targetFrame().label != 6) {
5753 velocity += facing * multiplier * speed * 700 * scale;
5754 velspeed = findLength(&velocity);
5755 if (velspeed > speed * 45 * scale) {
5756 velocity /= velspeed;
5757 velspeed = speed * 45 * scale;
5758 velocity *= velspeed;
5760 velocity.y += gravity * multiplier * 20;
5761 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5762 velspeed = findLength(&velocity);
5763 velocity = flatfacing * velspeed;
5766 if (animTarget == sneakanim || animTarget == walkanim) {
5767 velocity += facing * multiplier * speed * 700 * scale;
5768 velspeed = findLength(&velocity);
5769 if (velspeed > speed * 12 * scale) {
5770 velocity /= velspeed;
5771 velspeed = speed * 12 * scale;
5772 velocity *= velspeed;
5774 velocity.y += gravity * multiplier * 20;
5775 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5776 velspeed = findLength(&velocity);
5777 velocity = flatfacing * velspeed;
5780 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5781 velocity += facing * multiplier * speed * 700 * scale;
5782 velspeed = findLength(&velocity);
5783 if (velspeed > speed * 2 * scale) {
5784 velocity /= velspeed;
5785 velspeed = speed * 2 * scale;
5786 velocity *= velspeed;
5788 velocity.y += gravity * multiplier * 20;
5789 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5790 velspeed = findLength(&velocity);
5791 velocity = flatfacing * velspeed;
5795 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5796 velocity -= facing * multiplier * speed * 700 * scale;
5797 velspeed = findLength(&velocity);
5798 if (velspeed > speed * 2 * scale) {
5799 velocity /= velspeed;
5800 velspeed = speed * 2 * scale;
5801 velocity *= velspeed;
5803 velocity.y += gravity * multiplier * 20;
5804 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5805 velspeed = findLength(&velocity);
5806 velocity = flatfacing * velspeed * -1;
5809 if (animTarget == fightsidestep) {
5810 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5811 velspeed = findLength(&velocity);
5812 if (velspeed > speed * 12 * scale) {
5813 velocity /= velspeed;
5814 velspeed = speed * 12 * scale;
5815 velocity *= velspeed;
5817 velocity.y += gravity * multiplier * 20;
5818 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5819 velspeed = findLength(&velocity);
5820 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5823 if (animTarget == staggerbackhighanim) {
5824 coords -= facing * multiplier * speed * 16 * scale;
5827 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5828 coords -= facing * multiplier * speed * 20 * scale;
5832 if (animTarget == backhandspringanim) {
5833 //coords-=facing*multiplier*50*scale;
5834 velocity += facing * multiplier * speed * 700 * scale * -1;
5835 velspeed = findLength(&velocity);
5836 if (velspeed > speed * 50 * scale) {
5837 velocity /= velspeed;
5838 velspeed = speed * 50 * scale;
5839 velocity *= velspeed;
5841 velocity.y += gravity * multiplier * 20;
5842 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5843 velspeed = findLength(&velocity);
5844 velocity = flatfacing * velspeed * -1;
5846 if (animTarget == dodgebackanim) {
5847 //coords-=facing*multiplier*50*scale;
5848 velocity += facing * multiplier * speed * 700 * scale * -1;
5849 velspeed = findLength(&velocity);
5850 if (velspeed > speed * 60 * scale) {
5851 velocity /= velspeed;
5852 velspeed = speed * 60 * scale;
5853 velocity *= velspeed;
5855 velocity.y += gravity * multiplier * 20;
5856 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5857 velspeed = findLength(&velocity);
5858 velocity = flatfacing * velspeed * -1;
5861 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5862 velspeed = findLength(&velocity);
5866 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5867 velocity.y += gravity * multiplier;
5870 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5871 coords += velocity * multiplier;
5873 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5874 if (isFlip() && targetFrame().label == 7)
5877 if (animTarget == jumpupanim) {
5879 animTarget = getIdle();
5886 pause_sound(whooshsound);
5887 OPENAL_SetVolume(channels[whooshsound], 0);
5890 if (animTarget == jumpdownanim || isFlip()) {
5891 if (isFlip())jumppower = -4;
5892 animTarget = getLanding();
5893 emit_sound_at(landsound, coords, 128.);
5896 addEnvSound(coords);
5901 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5902 coords.y += gravity * multiplier * 2;
5903 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5904 coords.y = terrain.getHeight(coords.x, coords.z);
5909 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)) {
5910 velspeed = findLength(&velocity);
5912 if (velspeed < multiplier * 300 * scale) {
5915 velocity -= velocity / velspeed * multiplier * 300 * scale;
5917 if (velspeed > 5 && (isLanding() || isLandhard())) {
5918 skiddingdelay += multiplier;
5919 if (skiddelay <= 0) {
5920 FootLand(leftfoot, .5);
5921 FootLand(rightfoot, .5);
5930 velspeed = findLength(&velocity);
5932 if (velspeed > 5 && (isLanding() || isLandhard())) {
5933 skiddingdelay += multiplier;
5934 if (skiddelay <= 0) {
5935 FootLand(leftfoot, .5);
5936 FootLand(rightfoot, .5);
5944 if (skiddingdelay < 0)
5945 skiddingdelay += multiplier;
5946 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5948 if (!onterrain || environment == grassyenvironment) {
5949 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5951 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5955 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5956 terrainnormal = victim->coords - coords;
5957 Normalise(&terrainnormal);
5958 targetyaw = -asin(0 - terrainnormal.x);
5959 targetyaw *= 360 / 6.28;
5960 if (terrainnormal.z < 0)
5961 targetyaw = 180 - targetyaw;
5962 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5965 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5966 targetyaw = victim->targetyaw;
5968 if (animTarget == rabbittacklinganim) {
5969 coords = victim->coords;
5972 skeleton.oldfree = skeleton.free;
5976 midterrain.x = terrain.size * terrain.scale / 2;
5977 midterrain.z = terrain.size * terrain.scale / 2;
5978 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5980 tempposit = coords - midterrain;
5982 Normalise(&tempposit);
5983 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5984 coords.x = tempposit.x + midterrain.x;
5985 coords.z = tempposit.z + midterrain.z;
5991 * inverse kinematics helper function
5993 void IKHelper(Person *p, float interp)
5995 XYZ point, change, change2;
5996 float heightleft, heightright;
5998 // TODO: implement localToWorld and worldToLocal
5999 // but keep in mind it won't be the same math if player is ragdolled or something
6000 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6001 // then comb through code for places where to use it
6003 // point = localToWorld(jointPos(leftfoot))
6004 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6005 // adjust height of foot
6006 heightleft = terrain.getHeight(point.x, point.z) + .04;
6007 point.y = heightleft;
6008 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6009 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6010 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6011 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6012 // move ankle along with foot
6013 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6014 // average knee pos between old and new pos
6015 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6017 // do same as above for right leg
6018 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6019 heightright = terrain.getHeight(point.x, point.z) + .04;
6020 point.y = heightright;
6021 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6022 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6023 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6024 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6025 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6027 // fix up skeleton now that we've moved body parts?
6028 p->skeleton.DoConstraints(&p->coords, &p->scale);
6035 int Person::DrawSkeleton()
6037 int oldplayerdetail;
6038 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6039 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6049 glAlphaFunc(GL_GREATER, 0.0001);
6051 float terrainheight;
6055 if (!isnormal(tilt))
6057 if (!isnormal(tilt2))
6059 oldplayerdetail = playerdetail;
6061 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6064 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6067 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6072 if (playerdetail != oldplayerdetail) {
6074 normalsupdatedelay = 0;
6076 static float updatedelaychange;
6077 static float morphness;
6078 static float framemult;
6080 skeleton.FindForwards();
6081 if (howactive == typesittingwall) {
6082 skeleton.specialforward[1] = 0;
6083 skeleton.specialforward[1].z = 1;
6089 static int weaponattachmuscle;
6090 static int weaponrotatemuscle;
6091 static XYZ weaponpoint;
6092 static int start, endthing;
6093 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6094 if (!isSleeping() && !isSitting()) {
6095 // TODO: give these meaningful names
6096 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6097 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6098 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6099 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6101 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6103 if (creature == wolftype)
6107 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6108 IKHelper(this, target);
6109 if (creature == wolftype)
6110 IKHelper(this, target);
6113 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6114 IKHelper(this, 1 - target);
6115 if (creature == wolftype)
6116 IKHelper(this, 1 - target);
6120 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()))
6123 targetheadyaw = -targetyaw;
6124 targetheadpitch = 0;
6125 if (Animation::animations[animTarget].attack == 3)
6126 targetheadyaw += 180;
6128 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6129 skeleton.drawmodel.vertex[i] = 0;
6130 skeleton.drawmodel.vertex[i].y = 999;
6132 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6133 skeleton.drawmodellow.vertex[i] = 0;
6134 skeleton.drawmodellow.vertex[i].y = 999;
6136 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6137 skeleton.drawmodelclothes.vertex[i] = 0;
6138 skeleton.drawmodelclothes.vertex[i].y = 999;
6140 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6141 // convenience renames
6142 const int p1 = skeleton.muscles[i].parent1->label;
6143 const int p2 = skeleton.muscles[i].parent2->label;
6145 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6150 if (p1 == righthand || p2 == righthand) {
6151 morphness = righthandmorphness;
6152 start = righthandmorphstart;
6153 endthing = righthandmorphend;
6155 if (p1 == lefthand || p2 == lefthand) {
6156 morphness = lefthandmorphness;
6157 start = lefthandmorphstart;
6158 endthing = lefthandmorphend;
6160 if (p1 == head || p2 == head) {
6161 morphness = headmorphness;
6162 start = headmorphstart;
6163 endthing = headmorphend;
6165 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6166 morphness = chestmorphness;
6167 start = chestmorphstart;
6168 endthing = chestmorphend;
6170 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6171 morphness = tailmorphness;
6172 start = tailmorphstart;
6173 endthing = tailmorphend;
6176 skeleton.FindRotationMuscle(i, animTarget);
6177 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6178 glMatrixMode(GL_MODELVIEW);
6182 glRotatef(tilt2, 1, 0, 0);
6184 glRotatef(tilt, 0, 0, 1);
6187 glTranslatef(mid.x, mid.y, mid.z);
6189 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6190 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6192 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6193 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6195 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6196 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6198 if (playerdetail || skeleton.free == 3) {
6199 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6200 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6201 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6202 glMatrixMode(GL_MODELVIEW);
6204 if (p1 == abdomen || p2 == abdomen)
6205 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6206 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6207 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6208 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6209 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6210 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6211 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6212 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6213 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6214 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6215 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6216 if (p1 == head || p2 == head)
6217 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6218 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6219 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6220 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6221 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6222 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6223 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6227 if (!playerdetail || skeleton.free == 3) {
6228 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6229 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6230 glMatrixMode(GL_MODELVIEW);
6232 if (p1 == abdomen || p2 == abdomen)
6233 glTranslatef(v0.x * proportionbody.x,
6234 v0.y * proportionbody.y,
6235 v0.z * proportionbody.z);
6236 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6237 glTranslatef(v0.x * proportionarms.x,
6238 v0.y * proportionarms.y,
6239 v0.z * proportionarms.z);
6240 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6241 glTranslatef(v0.x * proportionlegs.x,
6242 v0.y * proportionlegs.y,
6243 v0.z * proportionlegs.z);
6244 if (p1 == head || p2 == head)
6245 glTranslatef(v0.x * proportionhead.x,
6246 v0.y * proportionhead.y,
6247 v0.z * proportionhead.z);
6249 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6250 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6251 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6252 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6258 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6259 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6261 glMatrixMode(GL_MODELVIEW);
6265 glRotatef(tilt2, 1, 0, 0);
6267 glRotatef(tilt, 0, 0, 1);
6268 glTranslatef(mid.x, mid.y, mid.z);
6269 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6270 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6272 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6273 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6275 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6276 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6278 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6279 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6280 glMatrixMode(GL_MODELVIEW);
6282 if (p1 == abdomen || p2 == abdomen)
6283 glTranslatef(v0.x * proportionbody.x,
6284 v0.y * proportionbody.y,
6285 v0.z * proportionbody.z);
6286 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6287 glTranslatef(v0.x * proportionarms.x,
6288 v0.y * proportionarms.y,
6289 v0.z * proportionarms.z);
6290 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6291 glTranslatef(v0.x * proportionlegs.x,
6292 v0.y * proportionlegs.y,
6293 v0.z * proportionlegs.z);
6294 if (p1 == head || p2 == head)
6295 glTranslatef(v0.x * proportionhead.x,
6296 v0.y * proportionhead.y,
6297 v0.z * proportionhead.z);
6298 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6299 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6300 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6301 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6306 updatedelay = 1 + (float)(Random() % 100) / 1000;
6308 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6309 normalsupdatedelay = 1;
6310 if (playerdetail || skeleton.free == 3)
6311 skeleton.drawmodel.CalculateNormals(0);
6312 if (!playerdetail || skeleton.free == 3)
6313 skeleton.drawmodellow.CalculateNormals(0);
6314 if (skeleton.clothes)
6315 skeleton.drawmodelclothes.CalculateNormals(0);
6317 if (playerdetail || skeleton.free == 3)
6318 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6319 if (!playerdetail || skeleton.free == 3)
6320 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6321 if (skeleton.clothes) {
6322 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6327 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6328 if (updatedelaychange > -realmultiplier * 30)
6329 updatedelaychange = -realmultiplier * 30;
6330 if (updatedelaychange > -framemult * 4)
6331 updatedelaychange = -framemult * 4;
6332 if (skeleton.free == 1)
6333 updatedelaychange *= 6;
6335 updatedelaychange *= 8;
6336 updatedelay += updatedelaychange;
6338 glMatrixMode(GL_MODELVIEW);
6340 glTranslatef(coords.x, coords.y - .02, coords.z);
6341 if (!skeleton.free) {
6342 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6343 glRotatef(yaw, 0, 1, 0);
6347 glColor4f(.4, 1, .4, 1);
6348 glDisable(GL_LIGHTING);
6349 glDisable(GL_TEXTURE_2D);
6352 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6353 XYZ &v0 = skeleton.drawmodel.vertex[i];
6354 glVertex3f(v0.x, v0.y, v0.z);
6361 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6362 const XYZ &v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6363 const XYZ &v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6364 const XYZ &v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6365 glVertex3f(v0.x, v0.y, v0.z);
6366 glVertex3f(v1.x, v1.y, v1.z);
6367 glVertex3f(v1.x, v1.y, v1.z);
6368 glVertex3f(v2.x, v2.y, v2.z);
6369 glVertex3f(v2.x, v2.y, v2.z);
6370 glVertex3f(v0.x, v0.y, v0.z);
6377 terrainlight = terrain.getLighting(coords.x, coords.z);
6378 distance = distsq(&viewer, &coords);
6379 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6383 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6384 if (terrainheight < 1)
6386 if (terrainheight > 1.7)
6387 terrainheight = 1.7;
6389 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6390 glDisable(GL_BLEND);
6391 glAlphaFunc(GL_GREATER, 0.0001);
6392 glEnable(GL_TEXTURE_2D);
6394 glDisable(GL_TEXTURE_2D);
6395 glColor4f(.7, .35, 0, .5);
6397 glEnable(GL_LIGHTING);
6400 if (Tutorial::active && id != 0) {
6401 glColor4f(.7, .7, .7, 0.6);
6403 glEnable(GL_LIGHTING);
6405 if (canattack && cananger)
6406 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6407 glDisable(GL_TEXTURE_2D);
6408 glColor4f(1, 0, 0, 0.8);
6410 glMatrixMode(GL_TEXTURE);
6412 glTranslatef(0, -smoketex, 0);
6413 glTranslatef(-smoketex, 0, 0);
6417 if (Tutorial::active && (id != 0))
6418 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6420 skeleton.drawmodel.draw();
6423 if (!playerdetail) {
6424 if (Tutorial::active && (id != 0))
6425 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6427 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6430 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6431 if (Tutorial::active && id != 0) {
6433 glMatrixMode(GL_MODELVIEW);
6434 glEnable(GL_TEXTURE_2D);
6435 glColor4f(.7, .7, .7, 0.6);
6437 glEnable(GL_LIGHTING);
6439 if (canattack && cananger)
6440 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6441 glDisable(GL_TEXTURE_2D);
6442 glColor4f(1, 0, 0, 0.8);
6444 glMatrixMode(GL_TEXTURE);
6446 glTranslatef(0, -smoketex * .6, 0);
6447 glTranslatef(smoketex * .6, 0, 0);
6450 if (Tutorial::active && (id != 0))
6451 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6453 skeleton.drawmodel.draw();
6456 if (!playerdetail) {
6457 if (Tutorial::active && (id != 0))
6458 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6460 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6465 if (Tutorial::active && id != 0) {
6467 glMatrixMode(GL_MODELVIEW);
6468 glEnable(GL_TEXTURE_2D);
6470 if (skeleton.clothes) {
6474 skeleton.drawmodelclothes.draw();
6476 skeleton.drawmodelclothes.drawimmediate();
6482 if (num_weapons > 0) {
6483 for (k = 0; k < num_weapons; k++) {
6484 int i = weaponids[k];
6485 if (weaponactive == k) {
6486 if (weapons[i].getType() != staff) {
6487 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6488 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6489 weaponattachmuscle = j;
6492 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6493 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) {
6494 weaponrotatemuscle = j;
6497 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6498 if (creature == wolftype)
6499 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6501 if (weapons[i].getType() == staff) {
6502 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6503 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6504 weaponattachmuscle = j;
6507 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6508 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) {
6509 weaponrotatemuscle = j;
6512 //weaponpoint=jointPos(rightwrist);
6513 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6514 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6515 XYZ tempnormthing, vec1, vec2;
6516 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6517 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6518 CrossProduct(&vec1, &vec2, &tempnormthing);
6519 Normalise(&tempnormthing);
6520 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6521 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6524 if (weaponactive != k && weaponstuck != k) {
6525 if (weapons[i].getType() == knife)
6526 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6527 if (weapons[i].getType() == sword)
6528 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6529 if (weapons[i].getType() == staff)
6530 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6531 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6532 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) {
6533 weaponrotatemuscle = j;
6537 if (weaponstuck == k) {
6538 if (weaponstuckwhere == 0)
6539 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6541 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6542 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6543 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) {
6544 weaponrotatemuscle = j;
6548 if (skeleton.free) {
6549 weapons[i].position = weaponpoint * scale + coords;
6550 weapons[i].bigrotation = 0;
6551 weapons[i].bigtilt = 0;
6552 weapons[i].bigtilt2 = 0;
6554 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;
6555 weapons[i].bigrotation = yaw;
6556 weapons[i].bigtilt = tilt;
6557 weapons[i].bigtilt2 = tilt2;
6559 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6560 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6561 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6562 if (weaponactive == k) {
6563 if (weapons[i].getType() == knife) {
6564 weapons[i].smallrotation = 180;
6565 weapons[i].smallrotation2 = 0;
6566 if (isCrouch() || wasCrouch()) {
6567 weapons[i].smallrotation2 = 20;
6569 if (animTarget == hurtidleanim) {
6570 weapons[i].smallrotation2 = 50;
6572 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6573 XYZ temppoint1, temppoint2;
6576 temppoint1 = jointPos(righthand);
6577 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6578 distance = findDistance(&temppoint1, &temppoint2);
6579 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6580 weapons[i].rotation2 *= 360 / 6.28;
6583 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6584 weapons[i].rotation1 *= 360 / 6.28;
6585 weapons[i].rotation3 = 0;
6586 weapons[i].smallrotation = -90;
6587 weapons[i].smallrotation2 = 0;
6588 if (temppoint1.x > temppoint2.x)
6589 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6591 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6592 XYZ temppoint1, temppoint2;
6595 temppoint1 = jointPos(righthand);
6596 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6597 distance = findDistance(&temppoint1, &temppoint2);
6598 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6599 weapons[i].rotation2 *= 360 / 6.28;
6602 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6603 weapons[i].rotation1 *= 360 / 6.28;
6604 weapons[i].rotation3 = 0;
6605 weapons[i].smallrotation = 90;
6606 weapons[i].smallrotation2 = 0;
6607 if (temppoint1.x > temppoint2.x)
6608 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6610 if (animTarget == knifethrowanim) {
6611 weapons[i].smallrotation = 90;
6612 //weapons[i].smallrotation2=-90;
6613 weapons[i].smallrotation2 = 0;
6614 weapons[i].rotation1 = 0;
6615 weapons[i].rotation2 = 0;
6616 weapons[i].rotation3 = 0;
6618 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6619 weapons[i].smallrotation = -90;
6620 weapons[i].rotation1 = 0;
6621 weapons[i].rotation2 = 0;
6622 weapons[i].rotation3 = 0;
6625 if (weapons[i].getType() == sword) {
6626 weapons[i].smallrotation = 0;
6627 weapons[i].smallrotation2 = 0;
6628 if (animTarget == knifethrowanim) {
6629 weapons[i].smallrotation = -90;
6630 weapons[i].smallrotation2 = 0;
6631 weapons[i].rotation1 = 0;
6632 weapons[i].rotation2 = 0;
6633 weapons[i].rotation3 = 0;
6635 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)) {
6636 XYZ temppoint1, temppoint2;
6639 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6640 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6641 distance = findDistance(&temppoint1, &temppoint2);
6642 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6643 weapons[i].rotation2 *= 360 / 6.28;
6646 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6647 weapons[i].rotation1 *= 360 / 6.28;
6648 weapons[i].rotation3 = 0;
6649 weapons[i].smallrotation = 90;
6650 weapons[i].smallrotation2 = 0;
6651 if (temppoint1.x > temppoint2.x)
6652 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6655 if (weapons[i].getType() == staff) {
6656 weapons[i].smallrotation = 100;
6657 weapons[i].smallrotation2 = 0;
6658 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6659 XYZ temppoint1, temppoint2;
6662 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6663 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6664 distance = findDistance(&temppoint1, &temppoint2);
6665 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6666 weapons[i].rotation2 *= 360 / 6.28;
6669 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6670 weapons[i].rotation1 *= 360 / 6.28;
6671 weapons[i].rotation3 = 0;
6672 weapons[i].smallrotation = 90;
6673 weapons[i].smallrotation2 = 0;
6674 if (temppoint1.x > temppoint2.x)
6675 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6679 if (weaponactive != k && weaponstuck != k) {
6680 if (weapons[i].getType() == knife) {
6681 weapons[i].smallrotation = -70;
6682 weapons[i].smallrotation2 = 10;
6684 if (weapons[i].getType() == sword) {
6685 weapons[i].smallrotation = -100;
6686 weapons[i].smallrotation2 = -8;
6688 if (weapons[i].getType() == staff) {
6689 weapons[i].smallrotation = -100;
6690 weapons[i].smallrotation2 = -8;
6693 if (weaponstuck == k) {
6694 if (weaponstuckwhere == 0)
6695 weapons[i].smallrotation = 180;
6697 weapons[i].smallrotation = 0;
6698 weapons[i].smallrotation2 = 10;
6707 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6709 if (animCurrent != animTarget)
6711 if (skeleton.free == 2)
6720 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6722 static float distance;
6723 static float olddistance;
6724 static int intersecting;
6725 static int firstintersecting;
6728 static XYZ start, end;
6729 static float slopethreshold = -.4;
6731 firstintersecting = -1;
6735 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6738 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6739 for (int i = 0; i < 4; i++) {
6740 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
6741 if (model->Triangles[j].facenormal.y <= slopethreshold) {
6743 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)));
6744 if (distance < radius) {
6745 point = *p1 - model->Triangles[j].facenormal * distance;
6746 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]]))
6749 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6750 &model->vertex[model->Triangles[j].vertex[1]],
6753 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6754 &model->vertex[model->Triangles[j].vertex[2]],
6757 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6758 &model->vertex[model->Triangles[j].vertex[2]],
6761 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
6765 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)) {
6766 p1->y = point.y + radius;
6767 if ((animTarget == jumpdownanim || isFlip())) {
6768 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6771 if (animTarget == jumpupanim) {
6773 animTarget = getIdle();
6780 pause_sound(whooshsound);
6781 OPENAL_SetVolume(channels[whooshsound], 0);
6784 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6787 animTarget = getLanding();
6788 emit_sound_at(landsound, coords, 128.);
6791 addEnvSound(coords);
6798 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6799 olddistance = distance;
6800 firstintersecting = j;
6805 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
6806 if (model->Triangles[j].facenormal.y > slopethreshold) {
6809 start.y -= radius / 4;
6810 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6811 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6812 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6813 distance = abs((model->Triangles[j].facenormal.x * start.x)
6814 + (model->Triangles[j].facenormal.y * start.y)
6815 + (model->Triangles[j].facenormal.z * start.z)
6816 - ((model->Triangles[j].facenormal.x * v0.x)
6817 + (model->Triangles[j].facenormal.y * v0.y)
6818 + (model->Triangles[j].facenormal.z * v0.z)));
6819 if (distance < radius * .5) {
6820 point = start - model->Triangles[j].facenormal * distance;
6821 if (PointInTriangle( &point, model->Triangles[j].facenormal, &v0, &v1, &v2))
6824 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6826 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6828 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6830 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
6831 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6833 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;
6834 if (findLengthfast(&start) < findLengthfast(&velocity))
6837 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
6840 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6841 olddistance = distance;
6842 firstintersecting = j;
6849 *p = DoRotation(*p, 0, *rotate, 0);
6852 *p1 = DoRotation(*p1, 0, *rotate, 0);
6854 return firstintersecting;
6857 int findPathDist(int start, int end)
6862 unsigned int smallestcount = 1000;
6863 for (char i = 0; i < 50; i++) {
6864 unsigned int count = 0;
6869 while (last != end && count < 30) {
6871 for (int j = 0; j < Game::numpathpoints; j++) {
6872 if (j != last && j != last2 && j != last3 && j != last4) {
6874 if (Game::numpathpointconnect[j])
6875 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6876 if (Game::pathpointconnect[j][k] == last)connected = 1;
6879 if (Game::numpathpointconnect[last])
6880 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
6881 if (Game::pathpointconnect[last][k] == j)connected = 1;
6884 if (closest == -1 || Random() % 2 == 0) {
6895 if (count < smallestcount) {
6896 smallestcount = count;
6899 return smallestcount;
6902 void Person::takeWeapon(int weaponId)
6905 weapons[weaponId].owner = id;
6906 if (num_weapons > 0) {
6907 weaponids[num_weapons] = weaponids[0];
6910 weaponids[0] = weaponId;
6913 void Person::addClothes()
6915 if (numclothes > 0) {
6916 for (int i = 0; i < numclothes; i++) {
6923 bool Person::addClothes(const int& clothesId)
6926 const std::string fileName = clothes[clothesId];
6928 GLubyte* array = &skeleton.skinText[0];
6932 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6937 float tintr = clothestintr[clothesId];
6938 float tintg = clothestintg[clothesId];
6939 float tintb = clothestintb[clothesId];
6941 if (tintr > 1) tintr = 1;
6942 if (tintg > 1) tintg = 1;
6943 if (tintb > 1) tintb = 1;
6945 if (tintr < 0) tintr = 0;
6946 if (tintg < 0) tintg = 0;
6947 if (tintb < 0) tintb = 0;
6949 int bytesPerPixel = texture.bpp / 8;
6953 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6954 if (bytesPerPixel == 3)
6956 else if ((i + 1) % 4 == 0)
6957 alphanum = texture.data[i];
6958 if ((i + 1) % 4 || bytesPerPixel == 3) {
6960 texture.data[i] *= tintr;
6962 texture.data[i] *= tintg;
6964 texture.data[i] *= tintb;
6965 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6977 if (aitype != playercontrolled && !Dialog::inDialog()) {
6979 //disable movement in editor
6980 if (Game::editorenabled)
6984 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
6985 Person::players[0]->coords.y > coords.y + 2 &&
6986 !Person::players[0]->onterrain)
6990 if (aitype == pathfindtype) {
6991 if (finalpathfindpoint == -1) {
6992 float closestdistance;
6997 closestdistance = -1;
6998 for (int j = 0; j < Game::numpathpoints; j++) {
6999 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7000 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7002 finaltarget = Game::pathpoint[j];
7005 finalpathfindpoint = closest;
7006 for (int j = 0; j < Game::numpathpoints; j++) {
7007 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7008 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7009 if (sq(tempdist) < closestdistance)
7010 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7011 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7012 closestdistance = sq(tempdist);
7014 finaltarget = colpoint;
7018 finalpathfindpoint = closest;
7021 if (targetpathfindpoint == -1) {
7022 float closestdistance;
7027 closestdistance = -1;
7028 if (lastpathfindpoint == -1) {
7029 for (int j = 0; j < Game::numpathpoints; j++) {
7030 if (j != lastpathfindpoint)
7031 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7032 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7036 targetpathfindpoint = closest;
7037 for (int j = 0; j < Game::numpathpoints; j++)
7038 if (j != lastpathfindpoint)
7039 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7040 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint );
7041 if (sq(tempdist) < closestdistance) {
7042 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7043 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7044 closestdistance = sq(tempdist);
7049 targetpathfindpoint = closest;
7051 for (int j = 0; j < Game::numpathpoints; j++)
7052 if (j != lastpathfindpoint &&
7053 j != lastpathfindpoint2 &&
7054 j != lastpathfindpoint3 &&
7055 j != lastpathfindpoint4) {
7057 if (Game::numpathpointconnect[j])
7058 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7059 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7062 if (Game::numpathpointconnect[lastpathfindpoint])
7063 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7064 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7067 tempdist = findPathDist(j, finalpathfindpoint);
7068 if (closest == -1 || tempdist < closestdistance) {
7069 closestdistance = tempdist;
7074 targetpathfindpoint = closest;
7077 losupdatedelay -= multiplier;
7079 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7080 lookyaw = targetyaw;
7082 //reached target point
7083 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7084 lastpathfindpoint4 = lastpathfindpoint3;
7085 lastpathfindpoint3 = lastpathfindpoint2;
7086 lastpathfindpoint2 = lastpathfindpoint;
7087 lastpathfindpoint = targetpathfindpoint;
7088 if (lastpathfindpoint2 == -1)
7089 lastpathfindpoint2 = lastpathfindpoint;
7090 if (lastpathfindpoint3 == -1)
7091 lastpathfindpoint3 = lastpathfindpoint2;
7092 if (lastpathfindpoint4 == -1)
7093 lastpathfindpoint4 = lastpathfindpoint3;
7094 targetpathfindpoint = -1;
7096 if ( distsqflat(&coords, &finalfinaltarget) <
7097 distsqflat(&coords, &finaltarget) ||
7098 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7099 lastpathfindpoint == finalpathfindpoint) {
7100 aitype = passivetype;
7111 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7112 targetyaw += 90 * (whichdirection * 2 - 1);
7114 if (collided < 1 || animTarget != jumpupanim)
7116 if ((collided > .8 && jumppower >= 5))
7119 if ((!Tutorial::active || cananger) &&
7121 !Person::players[0]->dead &&
7122 distsq(&coords, &Person::players[0]->coords) < 400 &&
7124 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7125 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7126 !Game::editorenabled &&
7127 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7128 aitype = attacktypecutoff;
7129 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7130 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7131 !Game::editorenabled)
7132 aitype = attacktypecutoff;
7134 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7135 losupdatedelay = .2;
7136 for (unsigned j = 0; j < Person::players.size(); j++)
7137 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7138 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7139 if (distsq(&coords, &Person::players[j]->coords) < 400)
7140 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7141 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7142 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
7143 DoRotation(jointPos(head), 0, yaw, 0)
7145 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
7146 *Person::players[j]->scale + Person::players[j]->coords) ||
7147 (Person::players[j]->animTarget == hanganim &&
7148 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7149 aitype = searchtype;
7151 lastseen = Person::players[j]->coords;
7156 if (aitype == attacktypecutoff && Game::musictype != 2)
7157 if (creature != wolftype) {
7163 if (aitype != passivetype && Game::leveltime > .5)
7164 howactive = typeactive;
7166 if (aitype == passivetype) {
7167 aiupdatedelay -= multiplier;
7168 losupdatedelay -= multiplier;
7169 lastseentime += multiplier;
7170 pausetime -= multiplier;
7171 if (lastseentime > 1)
7174 if (aiupdatedelay < 0) {
7175 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7176 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7177 lookyaw = targetyaw;
7178 aiupdatedelay = .05;
7180 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7181 if (waypointtype[waypoint] == wppause)
7184 if (waypoint > numwaypoints - 1)
7190 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7201 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7202 if (!avoidsomething)
7203 targetyaw += 90 * (whichdirection * 2 - 1);
7205 XYZ leftpos, rightpos;
7206 float leftdist, rightdist;
7207 leftpos = coords + DoRotation(facing, 0, 90, 0);
7208 rightpos = coords - DoRotation(facing, 0, 90, 0);
7209 leftdist = distsq(&leftpos, &avoidwhere);
7210 rightdist = distsq(&rightpos, &avoidwhere);
7211 if (leftdist < rightdist)
7218 if (collided < 1 || animTarget != jumpupanim)
7220 if ((collided > .8 && jumppower >= 5))
7225 if (!Game::editorenabled) {
7226 if (howactive <= typesleeping)
7227 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7228 for (int j = 0; j < numenvsounds; j++) {
7229 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7230 if (vol > 0 && distsq(&coords, &envsound[j]) <
7231 2 * (vol + vol * (creature == rabbittype) * 3))
7232 aitype = attacktypecutoff;
7235 if (aitype != passivetype) {
7236 if (howactive == typesleeping)
7237 setTargetAnimation(getupfromfrontanim);
7238 howactive = typeactive;
7242 if (howactive < typesleeping &&
7243 ((!Tutorial::active || cananger) && hostile) &&
7244 !Person::players[0]->dead &&
7245 distsq(&coords, &Person::players[0]->coords) < 400 &&
7247 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7248 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7249 aitype = attacktypecutoff;
7250 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7251 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7252 aitype = attacktypecutoff;
7255 if (creature == wolftype) {
7257 for (unsigned j = 0; j < Person::players.size(); j++) {
7258 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7259 float smelldistance = 50;
7260 if (j == 0 && Person::players[j]->num_weapons > 0) {
7261 if (weapons[Person::players[j]->weaponids[0]].bloody)
7262 smelldistance = 100;
7263 if (Person::players[j]->num_weapons == 2)
7264 if (weapons[Person::players[j]->weaponids[1]].bloody)
7265 smelldistance = 100;
7268 smelldistance = 100;
7269 windsmell = windvector;
7270 Normalise(&windsmell);
7271 windsmell = windsmell * 2 + Person::players[j]->coords;
7272 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7273 aitype = attacktypecutoff;
7278 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7279 losupdatedelay = .2;
7280 for (unsigned j = 0; j < Person::players.size(); j++) {
7281 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7282 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7283 if (distsq(&coords, &Person::players[j]->coords) < 400)
7284 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7285 if ((-1 == Object::checkcollide(
7286 DoRotation(jointPos(head), 0, yaw, 0)*
7288 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
7289 Person::players[j]->scale + Person::players[j]->coords) &&
7290 !Person::players[j]->isWallJump()) ||
7291 (Person::players[j]->animTarget == hanganim &&
7292 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7294 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7299 if (lastseentime <= 0) {
7300 aitype = searchtype;
7302 lastseen = Person::players[j]->coords;
7310 if (aitype == attacktypecutoff && Game::musictype != 2) {
7311 if (creature != wolftype) {
7315 if (creature == wolftype) {
7325 if (aitype == searchtype) {
7326 aiupdatedelay -= multiplier;
7327 losupdatedelay -= multiplier;
7329 lastseentime -= multiplier;
7330 lastchecktime -= multiplier;
7332 if (isRun() && !onground) {
7333 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7334 XYZ test2 = coords + facing;
7336 XYZ test = coords + facing;
7338 j = Object::checkcollide(test2, test, laststanding);
7340 j = Object::checkcollide(test2, test);
7343 setTargetAnimation(getStop());
7346 //aitype=passivetype;
7347 aitype = pathfindtype;
7348 finalfinaltarget = waypoints[waypoint];
7349 finalpathfindpoint = -1;
7350 targetpathfindpoint = -1;
7351 lastpathfindpoint = -1;
7352 lastpathfindpoint2 = -1;
7353 lastpathfindpoint3 = -1;
7354 lastpathfindpoint4 = -1;
7359 //check out last seen location
7360 if (aiupdatedelay < 0) {
7361 targetyaw = roughDirectionTo(coords, lastseen);
7362 lookyaw = targetyaw;
7363 aiupdatedelay = .05;
7366 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7369 lastseen.x += (float(Random() % 100) - 50) / 25;
7370 lastseen.z += (float(Random() % 100) - 50) / 25;
7381 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7382 if (!avoidsomething)
7383 targetyaw += 90 * (whichdirection * 2 - 1);
7385 XYZ leftpos, rightpos;
7386 float leftdist, rightdist;
7387 leftpos = coords + DoRotation(facing, 0, 90, 0);
7388 rightpos = coords - DoRotation(facing, 0, 90, 0);
7389 leftdist = distsq(&leftpos, &avoidwhere);
7390 rightdist = distsq(&rightpos, &avoidwhere);
7391 if (leftdist < rightdist)
7398 if (collided < 1 || animTarget != jumpupanim)
7400 if ((collided > .8 && jumppower >= 5))
7403 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7404 for (int k = 0; k < numenvsounds; k++) {
7405 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7406 aitype = attacktypecutoff;
7410 if (!Person::players[0]->dead &&
7411 losupdatedelay < 0 &&
7412 !Game::editorenabled &&
7414 ((!Tutorial::active || cananger) && hostile)) {
7415 losupdatedelay = .2;
7416 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7417 aitype = attacktypecutoff;
7420 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7421 //TODO: factor out canSeePlayer()
7422 if (distsq(&coords, &Person::players[0]->coords) < 400)
7423 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7424 if ((Object::checkcollide(
7425 DoRotation(jointPos(head), 0, yaw, 0)*
7427 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
7428 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
7429 (Person::players[0]->animTarget == hanganim && normaldotproduct(
7430 Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7431 /* //TODO: changed j to 0 on a whim, make sure this is correct
7432 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7433 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7435 aitype = attacktypecutoff;
7440 if (lastseentime < 0) {
7441 //aitype=passivetype;
7443 aitype = pathfindtype;
7444 finalfinaltarget = waypoints[waypoint];
7445 finalpathfindpoint = -1;
7446 targetpathfindpoint = -1;
7447 lastpathfindpoint = -1;
7448 lastpathfindpoint2 = -1;
7449 lastpathfindpoint3 = -1;
7450 lastpathfindpoint4 = -1;
7454 if (aitype != gethelptype)
7457 //get help from buddies
7458 if (aitype == gethelptype) {
7459 runninghowlong += multiplier;
7460 aiupdatedelay -= multiplier;
7462 if (aiupdatedelay < 0 || ally == 0) {
7466 //TODO: factor out closest search somehow
7469 float closestdist = -1;
7470 for (unsigned k = 0; k < Person::players.size(); k++) {
7471 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7472 (Person::players[k]->howactive < typedead1) &&
7473 !Person::players[k]->skeleton.free &&
7474 (Person::players[k]->aitype == passivetype)) {
7475 float distance = distsq(&coords, &Person::players[k]->coords);
7476 if (closestdist == -1 || distance < closestdist) {
7477 closestdist = distance;
7483 if (closest != -1) {
7488 lastseen = Person::players[0]->coords;
7495 XYZ facing = coords;
7496 XYZ flatfacing = Person::players[ally]->coords;
7497 facing.y += jointPos(head).y * scale;
7498 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7499 if (-1 != Object::checkcollide(facing, flatfacing))
7502 //no available ally, run back to player
7504 Person::players[ally]->skeleton.free ||
7505 Person::players[ally]->aitype != passivetype ||
7506 lastseentime <= 0) {
7507 aitype = searchtype;
7513 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7514 lookyaw = targetyaw;
7515 aiupdatedelay = .05;
7518 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7519 aitype = searchtype;
7521 Person::players[ally]->aitype = searchtype;
7522 if (Person::players[ally]->lastseentime < lastseentime) {
7523 Person::players[ally]->lastseen = lastseen;
7524 Person::players[ally]->lastseentime = lastseentime;
7525 Person::players[ally]->lastchecktime = lastchecktime;
7529 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7530 if (!avoidsomething)
7531 targetyaw += 90 * (whichdirection * 2 - 1);
7533 XYZ leftpos, rightpos;
7534 float leftdist, rightdist;
7535 leftpos = coords + DoRotation(facing, 0, 90, 0);
7536 rightpos = coords - DoRotation(facing, 0, 90, 0);
7537 leftdist = distsq(&leftpos, &avoidwhere);
7538 rightdist = distsq(&rightpos, &avoidwhere);
7539 if (leftdist < rightdist)
7553 if (collided < 1 || animTarget != jumpupanim)
7555 if (collided > .8 && jumppower >= 5)
7559 //retreiving a weapon on the ground
7560 if (aitype == getweapontype) {
7561 aiupdatedelay -= multiplier;
7562 lastchecktime -= multiplier;
7564 if (aiupdatedelay < 0) {
7570 float closestdist = -1;
7571 for (unsigned k = 0; k < weapons.size(); k++)
7572 if (weapons[k].owner == -1) {
7573 float distance = distsq(&coords, &weapons[k].position);
7574 if (closestdist == -1 || distance < closestdist) {
7575 closestdist = distance;
7588 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7589 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7590 aitype = attacktypecutoff;
7593 if (!Person::players[0]->dead)
7595 if (weapons[ally].owner != -1 ||
7596 distsq(&coords, &weapons[ally].position) > 16) {
7597 aitype = attacktypecutoff;
7600 //TODO: factor these out as moveToward()
7601 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7602 lookyaw = targetyaw;
7603 aiupdatedelay = .05;
7607 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7608 if (!avoidsomething)
7609 targetyaw += 90 * (whichdirection * 2 - 1);
7611 XYZ leftpos, rightpos;
7612 float leftdist, rightdist;
7613 leftpos = coords + DoRotation(facing, 0, 90, 0);
7614 rightpos = coords - DoRotation(facing, 0, 90, 0);
7615 leftdist = distsq(&leftpos, &avoidwhere);
7616 rightdist = distsq(&rightpos, &avoidwhere);
7617 if (leftdist < rightdist)
7631 if (animTarget != crouchremoveknifeanim &&
7632 animTarget != removeknifeanim)
7633 throwtogglekeydown = 0;
7636 if (collided < 1 || animTarget != jumpupanim)
7638 if ((collided > .8 && jumppower >= 5))
7642 if (aitype == attacktypecutoff) {
7643 aiupdatedelay -= multiplier;
7644 //dodge or reverse rabbit kicks, knife throws, flips
7645 if (damage < damagetolerance * 2 / 3)
7646 if ((Person::players[0]->animTarget == rabbitkickanim ||
7647 Person::players[0]->animTarget == knifethrowanim ||
7648 (Person::players[0]->isFlip() &&
7649 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7650 !Person::players[0]->skeleton.free &&
7651 (aiupdatedelay < .1)) {
7655 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7656 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7657 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7658 if (abs(Random() % 2) == 0) {
7659 setTargetAnimation(backhandspringanim);
7661 setTargetAnimation(rollanim);
7663 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7666 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
7667 setTargetAnimation(flipanim);
7672 aiupdatedelay = .02;
7674 //get confused by flips
7675 if (Person::players[0]->isFlip() &&
7676 !Person::players[0]->skeleton.free &&
7677 Person::players[0]->animTarget != walljumprightkickanim &&
7678 Person::players[0]->animTarget != walljumpleftkickanim) {
7679 if (distsq(&Person::players[0]->coords, &coords) < 25)
7680 if ((1 - damage / damagetolerance) > .5)
7683 //go for weapon on the ground
7684 if (wentforweapon < 3)
7685 for (unsigned k = 0; k < weapons.size(); k++)
7686 if (creature != wolftype)
7687 if (num_weapons == 0 &&
7688 weapons[k].owner == -1 &&
7689 weapons[k].velocity.x == 0 &&
7690 weapons[k].velocity.z == 0 &&
7691 weapons[k].velocity.y == 0) {
7692 if (distsq(&coords, &weapons[k].position) < 16) {
7695 aitype = getweapontype;
7699 //dodge/reverse walljump kicks
7700 if (damage < damagetolerance / 2)
7701 if (Animation::animations[animTarget].height != highheight)
7702 if (damage < damagetolerance * .5 &&
7703 ((Person::players[0]->animTarget == walljumprightkickanim ||
7704 Person::players[0]->animTarget == walljumpleftkickanim) &&
7705 ((aiupdatedelay < .15 &&
7707 (aiupdatedelay < .08 &&
7708 difficulty != 2)))) {
7711 //walked off a ledge (?)
7712 if (isRun() && !onground)
7713 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7714 XYZ test2 = coords + facing;
7716 XYZ test = coords + facing;
7718 j = Object::checkcollide(test2, test, laststanding);
7720 j = Object::checkcollide(test2, test);
7723 setTargetAnimation(getStop());
7726 aitype = pathfindtype;
7727 finalfinaltarget = waypoints[waypoint];
7728 finalpathfindpoint = -1;
7729 targetpathfindpoint = -1;
7730 lastpathfindpoint = -1;
7731 lastpathfindpoint2 = -1;
7732 lastpathfindpoint3 = -1;
7733 lastpathfindpoint4 = -1;
7737 //lose sight of player in the air (?)
7738 if (Person::players[0]->coords.y > coords.y + 5 &&
7739 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7740 !Person::players[0]->onterrain) {
7741 aitype = pathfindtype;
7742 finalfinaltarget = waypoints[waypoint];
7743 finalpathfindpoint = -1;
7744 targetpathfindpoint = -1;
7745 lastpathfindpoint = -1;
7746 lastpathfindpoint2 = -1;
7747 lastpathfindpoint3 = -1;
7748 lastpathfindpoint4 = -1;
7750 //it's time to think (?)
7751 if (aiupdatedelay < 0 &&
7752 !Animation::animations[animTarget].attack &&
7753 animTarget != staggerbackhighanim &&
7754 animTarget != staggerbackhardanim &&
7755 animTarget != backhandspringanim &&
7756 animTarget != dodgebackanim) {
7758 if (weaponactive == -1 && num_weapons > 0)
7759 drawkeydown = Random() % 2;
7762 rabbitkickenabled = Random() % 2;
7764 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7765 XYZ targetpoint = Person::players[0]->coords;
7766 if (distsq(&Person::players[0]->coords, &coords) <
7767 distsq(&rotatetarget, &coords))
7768 targetpoint += Person::players[0]->velocity *
7769 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7770 targetyaw = roughDirectionTo(coords, targetpoint);
7771 lookyaw = targetyaw;
7772 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7774 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7776 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7777 distsq(&coords, &Person::players[0]->coords) < 9) &&
7778 Person::players[0]->weaponactive != -1)
7780 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7784 //chill out around the corpse
7785 if (Person::players[0]->dead) {
7787 if (Random() % 10 == 0)
7789 if (Random() % 100 == 0) {
7790 aitype = pathfindtype;
7791 finalfinaltarget = waypoints[waypoint];
7792 finalpathfindpoint = -1;
7793 targetpathfindpoint = -1;
7794 lastpathfindpoint = -1;
7795 lastpathfindpoint2 = -1;
7796 lastpathfindpoint3 = -1;
7797 lastpathfindpoint4 = -1;
7806 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7807 targetyaw += 90 * (whichdirection * 2 - 1);
7809 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7813 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7817 if (aitype != playercontrolled &&
7822 for (unsigned j = 0; j < Person::players.size(); j++)
7823 if (j != id && !Person::players[j]->skeleton.free &&
7824 Person::players[j]->hasvictim &&
7825 (Tutorial::active && reversaltrain ||
7826 Random() % 2 == 0 && difficulty == 2 ||
7827 Random() % 4 == 0 && difficulty == 1 ||
7828 Random() % 8 == 0 && difficulty == 0 ||
7829 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7830 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7831 (Random() % 2 == 0 || difficulty == 2) ||
7832 (isIdle() || isRun()) &&
7833 Person::players[j]->weaponactive != -1 ||
7834 Person::players[j]->animTarget == swordslashanim &&
7835 weaponactive != -1 ||
7836 Person::players[j]->animTarget == staffhitanim ||
7837 Person::players[j]->animTarget == staffspinhitanim))
7838 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7839 Person::players[j]->victim == Person::players[id] &&
7840 (Person::players[j]->animTarget == sweepanim ||
7841 Person::players[j]->animTarget == spinkickanim ||
7842 Person::players[j]->animTarget == staffhitanim ||
7843 Person::players[j]->animTarget == staffspinhitanim ||
7844 Person::players[j]->animTarget == winduppunchanim ||
7845 Person::players[j]->animTarget == upunchanim ||
7846 Person::players[j]->animTarget == wolfslapanim ||
7847 Person::players[j]->animTarget == knifeslashstartanim ||
7848 Person::players[j]->animTarget == swordslashanim &&
7849 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7850 weaponactive != -1))) {
7858 Person::players[target]->Reverse();
7863 if (collided > .8 && jumppower >= 5 ||
7864 distsq(&coords, &Person::players[0]->coords) > 400 &&
7866 creature == rabbittype)
7868 //TODO: why are we controlling the human?
7869 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7870 Person::players[0]->jumpkeydown = 0;
7871 if (Person::players[0]->animTarget == jumpdownanim &&
7872 distsq(&Person::players[0]->coords, &coords) < 40)
7877 if (Tutorial::active)
7882 XYZ facing = coords;
7883 XYZ flatfacing = Person::players[0]->coords;
7884 facing.y += jointPos(head).y * scale;
7885 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7887 if (-1 != Object::checkcollide(facing, flatfacing)) {
7890 if (lastseentime <= 0 &&
7891 (creature != wolftype ||
7892 weaponstuck == -1)) {
7893 aitype = searchtype;
7895 lastseen = Person::players[0]->coords;
7902 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7903 (aitype == attacktypecutoff ||
7904 aitype == searchtype))
7905 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7906 XYZ test = Person::players[0]->coords;
7908 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7912 if (aitype == passivetype && !(numwaypoints > 1) ||
7914 pause && damage > superpermanentdamage) {
7933 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7934 facing = flatfacing;
7936 if (aitype == attacktypecutoff) {
7937 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7938 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7939 } else if (howactive >= typesleeping) {
7940 targetheadyaw = targetyaw;
7941 targetheadpitch = 0;
7943 if (interestdelay <= 0) {
7944 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
7945 headtarget = coords;
7946 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
7947 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
7948 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
7949 headtarget += facing * 1.5;
7951 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
7952 targetheadpitch = pitchTo(coords, headtarget);