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())/*||(id==0&&attackkeydown)*/)
569 if (/*(id==0&&attackkeydown)||*/(!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;
591 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
593 if (howactive == typesitting) return sitanim;
594 if (howactive == typesittingwall) return sitwallanim;
595 if (howactive == typesleeping) return sleepanim;
596 if (howactive == typedead1) return dead1anim;
597 if (howactive == typedead2) return dead2anim;
598 if (howactive == typedead3) return dead3anim;
599 if (howactive == typedead4) return dead4anim;
600 if (creature == rabbittype) return bounceidleanim;
601 if (creature == wolftype) return wolfidle;
606 * crouch animation for this creature
608 int Person::getCrouch()
610 if (creature == rabbittype)
612 if (creature == wolftype)
613 return wolfcrouchanim;
618 * running animation for this creature (can be upright or all fours)
622 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
624 if (creature == wolftype && (!superruntoggle))
627 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
628 return rabbitrunninganim;
629 if (creature == wolftype && (superruntoggle))
630 return wolfrunninganim;
636 int Person::getStop()
638 if (creature == rabbittype)
640 if (creature == wolftype)
647 int Person::getLanding()
649 if (creature == rabbittype)
651 if (creature == wolftype)
658 int Person::getLandhard()
660 if (creature == rabbittype)
662 if (creature == wolftype)
663 return wolflandhardanim;
670 * Person::DoAnimations
673 SolidHitBonus(int playerid)
675 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
676 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
678 award_bonus(playerid, solidhit);
682 * spawns blood effects
684 void Person::DoBlood(float howmuch, int which)
686 // FIXME: should abstract out inputs
687 static int bleedxint, bleedyint;
689 if (bloodtoggle && !Tutorial::active) {
690 if (bleeding <= 0 && spurt) {
692 for (int i = 0; i < 3; i++) {
693 // emit blood particles
696 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
697 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
698 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
699 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
702 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
703 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
704 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
705 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
708 if (Random() % 2 == 0) // 50% chance
709 for (int i = 0; i < 3; i++) {
710 if (Random() % 2 != 0) {
711 // emit teeth particles
714 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
715 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
718 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
719 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
723 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
725 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
727 Sprite::setLastSpriteSpecial(3); // sets it to teeth
732 // FIXME: manipulating attributes
733 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
736 if (creature == rabbittype)
737 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) {
738 bleedxint = abs(Random() % 512);
739 bleedyint = abs(Random() % 512);
741 if (creature == wolftype)
742 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) {
743 bleedxint = abs(Random() % 512);
744 bleedyint = abs(Random() % 512);
748 bleedy /= realtexdetail;
749 bleedx /= realtexdetail;
750 direction = abs(Random() % 2) * 2 - 1;
759 * spawns big blood effects and ???
760 * modifies character's skin texture
762 void Person::DoBloodBig(float howmuch, int which)
764 static int bleedxint, bleedyint, i, j;
766 if (howmuch && id == 0)
769 if (!Tutorial::active || id == 0)
770 if (aitype != playercontrolled && howmuch > 0) {
774 if (creature == wolftype) {
775 int i = abs(Random() % 2);
777 whichsound = snarlsound;
779 whichsound = snarl2sound;
781 if (creature == rabbittype) {
782 int i = abs(Random() % 2);
784 whichsound = rabbitpainsound;
785 if (i == 1 && howmuch >= 2)
786 whichsound = rabbitpain1sound;
789 if (whichsound != -1) {
790 emit_sound_at(whichsound, coords);
795 if (id == 0 && howmuch > 0) {
799 if (bloodtoggle && decalstoggle && !Tutorial::active) {
800 if (bleeding <= 0 && spurt) {
802 for (int i = 0; i < 3; i++) {
803 // emit blood particles
804 // FIXME: copypaste from above
807 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
808 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
809 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
810 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
813 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
814 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
815 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
816 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
821 // weird texture manipulation code follows.
822 // looks like this is painting blood onto the character's skin texture
823 // FIXME: surely there's a better way
825 int offsetx = 0, offsety = 0;
827 offsety = Random() % 40;
828 offsetx = abs(Random() % 60);
830 if (which == 190 || which == 185) {
831 offsety = Random() % 40;
832 offsetx = abs(Random() % 100) - 20;
835 offsety = Random() % 10;
836 offsetx = Random() % 10;
839 offsety = Random() % 20;
840 offsetx = Random() % 20;
842 if (which == 220 || which == 215) {
852 if (creature == rabbittype)
853 for (i = 0; i < 512; i++) {
854 for (j = 0; j < 512; j++) {
855 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
856 if (i < startx) startx = i;
857 if (j < starty) starty = j;
858 if (i > endx) endx = i;
859 if (j > endy) endy = j;
863 if (creature == wolftype)
864 for (i = 0; i < 512; i++) {
865 for (j = 0; j < 512; j++) {
866 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
867 if (i < startx) startx = i;
868 if (j < starty) starty = j;
869 if (i > endx) endx = i;
870 if (j > endy) endy = j;
880 if (startx < 0) startx = 0;
881 if (starty < 0) starty = 0;
882 if (endx > 512 - 1) endx = 512 - 1;
883 if (endy > 512 - 1) endy = 512 - 1;
884 if (endx < startx) endx = startx;
885 if (endy < starty) endy = starty;
887 startx /= realtexdetail;
888 starty /= realtexdetail;
889 endx /= realtexdetail;
890 endy /= realtexdetail;
892 int texdetailint = realtexdetail;
894 if (creature == rabbittype)
895 for (i = startx; i < endx; i++) {
896 for (j = starty; j < endy; j++) {
897 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) {
898 color = Random() % 85 + 170;
899 where = i * skeleton.skinsize * 3 + j * 3;
900 if (skeleton.skinText[where + 0] > color / 2)
901 skeleton.skinText[where + 0] = color / 2;
902 skeleton.skinText[where + 1] = 0;
903 skeleton.skinText[where + 2] = 0;
907 if (creature == wolftype)
908 for (i = startx; i < endx; i++) {
909 for (j = starty; j < endy; j++) {
910 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) {
911 color = Random() % 85 + 170;
912 where = i * skeleton.skinsize * 3 + j * 3;
913 if (skeleton.skinText[where + 0] > color / 2)
914 skeleton.skinText[where + 0] = color / 2;
915 skeleton.skinText[where + 1] = 0;
916 skeleton.skinText[where + 2] = 0;
920 skeleton.drawmodel.textureptr.bind();
925 if (creature == rabbittype)
926 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) {
927 bleedxint = abs(Random() % 512);
928 bleedyint = abs(Random() % 512);
930 if (creature == wolftype)
931 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) {
932 bleedxint = abs(Random() % 512);
933 bleedyint = abs(Random() % 512);
935 bleedy = bleedxint + offsetx;
936 bleedx = bleedyint + offsety;
937 bleedy /= realtexdetail;
938 bleedx /= realtexdetail;
943 if (bleedx > skeleton.skinsize - 1)
944 bleedx = skeleton.skinsize - 1;
945 if (bleedy > skeleton.skinsize - 1)
946 bleedy = skeleton.skinsize - 1;
947 direction = abs(Random() % 2) * 2 - 1;
950 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
951 deathbleeding += bleeding;
952 bloodloss += bleeding * 3;
954 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
955 if (abs(Random() % 2) == 0) {
956 aitype = gethelptype;
959 aitype = attacktypecutoff;
967 * similar to DoBloodBig
969 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
973 static XYZ startpoint, endpoint, colpoint, movepoint;
974 static float rotationpoint;
976 static XYZ p1, p2, p3, p0;
979 float coordsx, coordsy;
982 if (bloodtoggle && decalstoggle && !Tutorial::active) {
985 where = DoRotation(where, 0, -yaw, 0);
993 // ray testing for a tri in the character model
994 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
995 if (whichtri != -1) {
996 // low level geometry math
998 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
999 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
1000 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
1002 bary.x = distsq(&p0, &p1);
1003 bary.y = distsq(&p0, &p2);
1004 bary.z = distsq(&p0, &p3);
1006 total = bary.x + bary.y + bary.z;
1011 bary.x = 1 - bary.x;
1012 bary.y = 1 - bary.y;
1013 bary.z = 1 - bary.z;
1015 total = bary.x + bary.y + bary.z;
1021 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1022 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1023 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1024 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1025 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1026 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1027 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;
1028 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;
1030 if (bleeding <= 0 && spurt) {
1032 for (int i = 0; i < 3; i++) {
1033 // emit blood particles
1034 // FIXME: more copypaste code
1036 if (skeleton.free) {
1037 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1038 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1039 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1040 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1043 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1044 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1045 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1046 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1051 // texture manipulation follows
1053 int offsetx = 0, offsety = 0;
1054 offsetx = (1 + coordsy) * 512 - 291;
1055 offsety = coordsx * 512 - 437;
1062 if (creature == rabbittype)
1063 for (i = 0; i < 512; i++) {
1064 for (j = 0; j < 512; j++) {
1065 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1066 if (i < startx) startx = i;
1067 if (j < starty) starty = j;
1068 if (i > endx) endx = i;
1069 if (j > endy) endy = j;
1073 if (creature == wolftype)
1074 for (i = 0; i < 512; i++) {
1075 for (j = 0; j < 512; j++) {
1076 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1077 if (i < startx) startx = i;
1078 if (j < starty) starty = j;
1079 if (i > endx) endx = i;
1080 if (j > endy) endy = j;
1089 if (startx < 0) startx = 0;
1090 if (starty < 0) starty = 0;
1091 if (endx > 512 - 1) endx = 512 - 1;
1092 if (endy > 512 - 1) endy = 512 - 1;
1093 if (endx < startx) endx = startx;
1094 if (endy < starty) endy = starty;
1096 startx /= realtexdetail;
1097 starty /= realtexdetail;
1098 endx /= realtexdetail;
1099 endy /= realtexdetail;
1101 int texdetailint = realtexdetail;
1103 if (creature == rabbittype)
1104 for (i = startx; i < endx; i++) {
1105 for (j = starty; j < endy; j++) {
1106 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) {
1107 color = Random() % 85 + 170;
1108 where = i * skeleton.skinsize * 3 + j * 3;
1109 if (skeleton.skinText[where + 0] > color / 2)
1110 skeleton.skinText[where + 0] = color / 2;
1111 skeleton.skinText[where + 1] = 0;
1112 skeleton.skinText[where + 2] = 0;
1113 } 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) {
1114 color = Random() % 85 + 170;
1115 where = i * skeleton.skinsize * 3 + j * 3;
1116 if (skeleton.skinText[where + 0] > color / 2)
1117 skeleton.skinText[where + 0] = color / 2;
1118 skeleton.skinText[where + 1] = 0;
1119 skeleton.skinText[where + 2] = 0;
1123 if (creature == wolftype)
1124 for (i = startx; i < endx; i++) {
1125 for (j = starty; j < endy; j++) {
1126 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) {
1127 color = Random() % 85 + 170;
1128 where = i * skeleton.skinsize * 3 + j * 3;
1129 if (skeleton.skinText[where + 0] > color / 2)
1130 skeleton.skinText[where + 0] = color / 2;
1131 skeleton.skinText[where + 1] = 0;
1132 skeleton.skinText[where + 2] = 0;
1133 } 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) {
1134 color = Random() % 85 + 170;
1135 where = i * skeleton.skinsize * 3 + j * 3;
1136 if (skeleton.skinText[where + 0] > color / 2)
1137 skeleton.skinText[where + 0] = color / 2;
1138 skeleton.skinText[where + 1] = 0;
1139 skeleton.skinText[where + 2] = 0;
1143 skeleton.drawmodel.textureptr.bind();
1146 bleedy = (1 + coordsy) * 512;
1147 bleedx = coordsx * 512;
1148 bleedy /= realtexdetail;
1149 bleedx /= realtexdetail;
1154 if (bleedx > skeleton.skinsize - 1)
1155 bleedx = skeleton.skinsize - 1;
1156 if (bleedy > skeleton.skinsize - 1)
1157 bleedy = skeleton.skinsize - 1;
1158 direction = abs(Random() % 2) * 2 - 1;
1163 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1164 deathbleeding += bleeding;
1165 bloodloss += bleeding * 3;
1167 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1168 if (abs(Random() % 2) == 0) {
1169 aitype = gethelptype;
1172 aitype = attacktypecutoff;
1183 * guessing this performs a reversal
1185 void Person::Reverse()
1187 if (!((victim->aitype == playercontrolled
1189 || staggerdelay <= 0)
1190 && victim->animTarget != jumpupanim
1191 && victim->animTarget != jumpdownanim
1192 && (!Tutorial::active || cananger)
1196 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1197 && (victim->id != 0 || difficulty >= 2)
1198 && (creature != wolftype || victim->creature == wolftype))
1201 if (animTarget == sweepanim) {
1202 animTarget = sweepreversedanim;
1203 animCurrent = sweepreversedanim;
1204 victim->animCurrent = sweepreversalanim;
1205 victim->animTarget = sweepreversalanim;
1207 if (animTarget == spinkickanim) {
1208 animTarget = spinkickreversedanim;
1209 animCurrent = spinkickreversedanim;
1210 victim->animCurrent = spinkickreversalanim;
1211 victim->animTarget = spinkickreversalanim;
1213 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1214 if (animTarget == rabbittacklinganim) {
1217 victim->frameCurrent = 6;
1218 victim->frameTarget = 7;
1220 animTarget = upunchreversedanim;
1221 animCurrent = upunchreversedanim;
1222 victim->animCurrent = upunchreversalanim;
1223 victim->animTarget = upunchreversalanim;
1225 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1226 if (victim->weaponactive != -1) {
1227 victim->throwtogglekeydown = 1;
1228 XYZ tempVelocity = victim->velocity * .2;
1229 if (tempVelocity.x == 0)
1230 tempVelocity.x = .1;
1231 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1232 victim->num_weapons--;
1233 if (victim->num_weapons) {
1234 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1235 if (victim->weaponstuck == victim->num_weapons)
1236 victim->weaponstuck = 0;
1239 victim->weaponactive = -1;
1240 for (unsigned j = 0; j < Person::players.size(); j++) {
1241 Person::players[j]->wentforweapon = 0;
1245 animTarget = staffhitreversedanim;
1246 animCurrent = staffhitreversedanim;
1247 victim->animCurrent = staffhitreversalanim;
1248 victim->animTarget = staffhitreversalanim;
1250 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1251 if (victim->weaponactive != -1) {
1252 victim->throwtogglekeydown = 1;
1253 XYZ tempVelocity = victim->velocity * .2;
1254 if (tempVelocity.x == 0)
1255 tempVelocity.x = .1;
1256 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1257 victim->num_weapons--;
1258 if (victim->num_weapons) {
1259 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1260 if (victim->weaponstuck == victim->num_weapons)
1261 victim->weaponstuck = 0;
1264 victim->weaponactive = -1;
1265 for (unsigned j = 0; j < Person::players.size(); j++) {
1266 Person::players[j]->wentforweapon = 0;
1269 animTarget = staffspinhitreversedanim;
1270 animCurrent = staffspinhitreversedanim;
1271 victim->animCurrent = staffspinhitreversalanim;
1272 victim->animTarget = staffspinhitreversalanim;
1274 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1275 if (victim->weaponactive != -1) {
1276 victim->throwtogglekeydown = 1;
1277 XYZ tempVelocity = victim->velocity * .2;
1278 if (tempVelocity.x == 0)
1279 tempVelocity.x = .1;
1280 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1281 victim->num_weapons--;
1282 if (victim->num_weapons) {
1283 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1284 if (victim->weaponstuck == victim->num_weapons)
1285 victim->weaponstuck = 0;
1288 victim->weaponactive = -1;
1289 for (unsigned j = 0; j < Person::players.size(); j++) {
1290 Person::players[j]->wentforweapon = 0;
1293 animTarget = swordslashreversedanim;
1294 animCurrent = swordslashreversedanim;
1295 victim->animCurrent = swordslashreversalanim;
1296 victim->animTarget = swordslashreversalanim;
1298 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1299 if (victim->weaponactive != -1) {
1300 victim->throwtogglekeydown = 1;
1301 XYZ tempVelocity = victim->velocity * .2;
1302 if (tempVelocity.x == 0)
1303 tempVelocity.x = .1;
1304 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1305 victim->num_weapons--;
1306 if (victim->num_weapons) {
1307 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1308 if (victim->weaponstuck == victim->num_weapons)
1309 victim->weaponstuck = 0;
1312 victim->weaponactive = -1;
1313 for (unsigned j = 0; j < Person::players.size(); j++) {
1314 Person::players[j]->wentforweapon = 0;
1317 animTarget = knifeslashreversedanim;
1318 animCurrent = knifeslashreversedanim;
1319 victim->animCurrent = knifeslashreversalanim;
1320 victim->animTarget = knifeslashreversalanim;
1322 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1323 victim->targettilt2 = targettilt2;
1324 victim->frameCurrent = frameCurrent;
1325 victim->frameTarget = frameTarget;
1326 victim->target = target;
1327 victim->velocity = 0;
1328 victim->oldcoords = victim->coords;
1329 victim->coords = coords;
1330 victim->targetyaw = targetyaw;
1331 victim->yaw = targetyaw;
1332 victim->victim = this->shared_from_this();
1334 if (animTarget == winduppunchanim) {
1335 animTarget = winduppunchblockedanim;
1336 victim->animTarget = blockhighleftanim;
1337 victim->frameTarget = 1;
1338 victim->target = .5;
1339 victim->victim = this->shared_from_this();
1340 victim->targetyaw = targetyaw + 180;
1342 if (animTarget == wolfslapanim) {
1343 animTarget = winduppunchblockedanim;
1344 victim->animTarget = blockhighleftanim;
1345 victim->frameTarget = 1;
1346 victim->target = .5;
1347 victim->victim = this->shared_from_this();
1348 victim->targetyaw = targetyaw + 180;
1350 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1351 animTarget = swordslashparriedanim;
1352 parriedrecently = .4;
1353 victim->parriedrecently = 0;
1354 victim->animTarget = swordslashparryanim;
1355 victim->frameTarget = 1;
1356 victim->target = .5;
1357 victim->victim = this->shared_from_this();
1358 victim->targetyaw = targetyaw + 180;
1360 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1361 if (victim->weaponactive != -1) {
1362 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1363 if (weapons[victim->weaponids[0]].getType() == staff)
1364 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1365 if (weapons[weaponids[0]].getType() == staff)
1366 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1367 emit_sound_at(swordstaffsound, victim->coords);
1369 emit_sound_at(metalhitsound, victim->coords);
1373 victim->Puff(righthand);
1375 victim->frameTarget = 0;
1376 victim->animTarget = staggerbackhighanim;
1377 victim->targetyaw = targetyaw + 180;
1379 aim = DoRotation(facing, 0, 90, 0) * 21;
1381 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1382 victim->num_weapons--;
1383 if (victim->num_weapons) {
1384 victim->weaponids[0] = victim->weaponids[num_weapons];
1385 if (victim->weaponstuck == victim->num_weapons)
1386 victim->weaponstuck = 0;
1388 victim->weaponactive = -1;
1389 for (unsigned i = 0; i < Person::players.size(); i++) {
1390 Person::players[i]->wentforweapon = 0;
1394 if (abs(Random() % 20) == 0) {
1395 if (weaponactive != -1) {
1396 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1397 if (weapons[victim->weaponids[0]].getType() == staff)
1398 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1399 if (weapons[weaponids[0]].getType() == staff)
1400 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1402 emit_sound_at(swordstaffsound, coords);
1404 emit_sound_at(metalhitsound, coords);
1412 animTarget = staggerbackhighanim;
1413 targetyaw = targetyaw + 180;
1415 aim = DoRotation(facing, 0, 90, 0) * 21;
1417 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1420 weaponids[0] = weaponids[num_weapons];
1421 if (weaponstuck == num_weapons)
1425 for (unsigned i = 0; i < Person::players.size(); i++) {
1426 Person::players[i]->wentforweapon = 0;
1433 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1434 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1435 victim->animTarget = dodgebackanim;
1436 victim->frameTarget = 0;
1440 rotatetarget = coords - victim->coords;
1441 Normalise(&rotatetarget);
1442 victim->targetyaw = -asin(0 - rotatetarget.x);
1443 victim->targetyaw *= 360 / 6.28;
1444 if (rotatetarget.z < 0)
1445 victim->targetyaw = 180 - victim->targetyaw;
1447 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1449 victim->lastattack3 = victim->lastattack2;
1450 victim->lastattack2 = victim->lastattack;
1451 victim->lastattack = victim->animTarget;
1453 victim->animTarget = sweepanim;
1454 victim->frameTarget = 0;
1458 rotatetarget = coords - victim->coords;
1459 Normalise(&rotatetarget);
1460 victim->targetyaw = -asin(0 - rotatetarget.x);
1461 victim->targetyaw *= 360 / 6.28;
1462 if (rotatetarget.z < 0)
1463 victim->targetyaw = 180 - victim->targetyaw;
1465 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1467 victim->lastattack3 = victim->lastattack2;
1468 victim->lastattack2 = victim->lastattack;
1469 victim->lastattack = victim->animTarget;
1474 victim->velocity = 0;
1476 if (aitype != playercontrolled) {
1478 if (escapednum < 2) {
1479 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1480 if ((Random() % chances) == 0) {
1486 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1493 void Person::DoDamage(float howmuch)
1497 damagetaken += howmuch / power;
1499 damagedealt += howmuch / power;
1503 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1508 if (!Tutorial::active) {
1509 damage += howmuch / power;
1510 permanentdamage += howmuch / 2 / power;
1511 superpermanentdamage += howmuch / 4 / power;
1514 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1516 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1520 camerashake += howmuch / 100;
1521 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1522 blackout = damage / damagetolerance;
1530 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile))
1531 aitype = attacktypecutoff;
1532 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1533 if (abs(Random() % 2) == 0) {
1534 aitype = gethelptype;
1537 aitype = attacktypecutoff;
1541 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1544 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1545 if (skeleton.free) {
1546 flatvelocity2 = skeleton.joints[i].velocity;
1547 flatfacing2 = skeleton.joints[i].position * scale + coords;
1549 flatvelocity2 = velocity;
1550 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1552 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1553 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1554 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1555 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1556 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1557 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1560 emit_sound_at(splattersound, coords);
1565 if (!dead && creature == wolftype) {
1566 award_bonus(0, Wolfbonus);
1573 if (!Tutorial::active || id == 0) {
1574 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1575 int whichsound = -1;
1577 if (creature == wolftype) {
1578 int i = abs(Random() % 2);
1580 whichsound = snarlsound;
1582 whichsound = snarl2sound;
1584 if (creature == rabbittype) {
1585 int i = abs(Random() % 2);
1587 whichsound = rabbitpainsound;
1588 if (i == 1 && damage > damagetolerance)
1589 whichsound = rabbitpain1sound;
1592 if (whichsound != -1) {
1593 emit_sound_at(whichsound, coords);
1594 addEnvSound(coords);
1602 * calculate/animate head facing direction?
1604 void Person::DoHead()
1606 static XYZ rotatearound;
1608 static float lookspeed = 500;
1610 if (!freeze && !winfreeze) {
1613 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1614 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1616 while (targetheadyaw > 180)targetheadyaw -= 360;
1617 while (targetheadyaw < -180)targetheadyaw += 360;
1619 if (targetheadyaw > 160)
1620 targetheadpitch = targetheadpitch * -1;
1621 if (targetheadyaw < -160)
1622 targetheadpitch = targetheadpitch * -1;
1623 if (targetheadyaw > 160)
1624 targetheadyaw = targetheadyaw - 180;
1625 if (targetheadyaw < -160)
1626 targetheadyaw = targetheadyaw + 180;
1628 if (targetheadpitch > 120)
1629 targetheadpitch = 120;
1630 if (targetheadpitch < -120)
1631 targetheadpitch = -120;
1632 if (targetheadyaw > 120)
1633 targetheadyaw = 120;
1634 if (targetheadyaw < -120)
1635 targetheadyaw = -120;
1638 targetheadpitch = 0;
1640 if (targetheadyaw > 80)
1642 if (targetheadyaw < -80)
1643 targetheadyaw = -80;
1644 if (targetheadpitch > 50)
1645 targetheadpitch = 50;
1646 if (targetheadpitch < -50)
1647 targetheadpitch = -50;
1650 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1651 headyaw = targetheadyaw;
1652 else if (headyaw > targetheadyaw) {
1653 headyaw -= multiplier * lookspeed;
1654 } else if (headyaw < targetheadyaw) {
1655 headyaw += multiplier * lookspeed;
1658 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1659 headpitch = targetheadpitch;
1660 else if (headpitch > targetheadpitch) {
1661 headpitch -= multiplier * lookspeed / 2;
1662 } else if (headpitch < targetheadpitch) {
1663 headpitch += multiplier * lookspeed / 2;
1666 rotatearound = jointPos(neck);
1667 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1671 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1672 facing = DoRotation(facing, headpitch * .4, 0, 0);
1673 facing = DoRotation(facing, 0, headyaw * .4, 0);
1676 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1677 facing = DoRotation(facing, headpitch * .8, 0, 0);
1678 facing = DoRotation(facing, 0, headyaw * .8, 0);
1681 if (animTarget == walkanim) {
1682 facing = DoRotation(facing, headpitch * .6, 0, 0);
1683 facing = DoRotation(facing, 0, headyaw * .6, 0);
1686 skeleton.specialforward[0] = facing;
1687 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1688 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1689 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1690 skeleton.FindRotationMuscle(i, animTarget);
1697 * ragdolls character?
1699 void Person::RagDoll(bool checkcollision)
1704 if (!skeleton.free) {
1707 if (id == 0 && isFlip())
1714 facing = DoRotation(facing, 0, yaw, 0);
1716 skeleton.freetime = 0;
1718 skeleton.longdead = 0;
1721 skeleton.broken = 0;
1722 skeleton.spinny = 1;
1724 skeleton.freefall = 1;
1726 if (!isnormal(velocity.x)) velocity.x = 0;
1727 if (!isnormal(velocity.y)) velocity.y = 0;
1728 if (!isnormal(velocity.z)) velocity.z = 0;
1729 if (!isnormal(yaw)) yaw = 0;
1730 if (!isnormal(coords.x)) coords = 0;
1731 if (!isnormal(tilt)) tilt = 0;
1732 if (!isnormal(tilt2)) tilt2 = 0;
1734 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1735 skeleton.joints[i].delay = 0;
1736 skeleton.joints[i].locked = 0;
1737 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1738 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1739 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1740 skeleton.joints[i].position.y += .1;
1741 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1742 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1745 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1746 skeleton.joints[i].velocity = 0;
1747 skeleton.joints[i].velchange = 0;
1749 skeleton.DoConstraints(&coords, &scale);
1750 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1751 skeleton.DoConstraints(&coords, &scale);
1752 skeleton.DoConstraints(&coords, &scale);
1753 skeleton.DoConstraints(&coords, &scale);
1754 skeleton.DoConstraints(&coords, &scale);
1757 speed = targetFrame().speed * 2;
1758 if (currentFrame().speed > targetFrame().speed) {
1759 speed = currentFrame().speed * 2;
1762 speed = transspeed * 2;
1766 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1767 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1768 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);
1770 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1771 change.x = (float)(Random() % 100) / 100;
1772 change.y = (float)(Random() % 100) / 100;
1773 change.z = (float)(Random() % 100) / 100;
1774 skeleton.joints[i].velocity += change;
1775 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1777 change.x = (float)(Random() % 100) / 100;
1778 change.y = (float)(Random() % 100) / 100;
1779 change.z = (float)(Random() % 100) / 100;
1780 skeleton.joints[i].velchange += change;
1781 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1784 if (checkcollision) {
1787 if (!skeleton.joints.empty()) {
1790 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1791 average += skeleton.joints[j].position;
1793 average /= skeleton.joints.size();
1794 coords += average * scale;
1795 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1796 skeleton.joints[j].position -= average;
1800 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1801 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1802 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1803 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; 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;
4294 static int bloodsize;
4295 static int startx, starty, endx, endy;
4296 static GLubyte color;
4297 static XYZ bloodvel;
4299 onfiredelay -= multiplier;
4300 if (onfiredelay < 0 && onfire) {
4301 if (Random() % 2 == 0) {
4307 crouchkeydowntime += multiplier;
4309 crouchkeydowntime = 0;
4310 jumpkeydowntime += multiplier;
4311 if (!jumpkeydown && skeleton.free)
4312 jumpkeydowntime = 0;
4314 if (hostile || damage > 0 || bloodloss > 0)
4317 if (isIdle() || isRun())
4320 if (num_weapons == 1 && weaponactive != -1)
4324 blooddimamount -= multiplier * .3;
4325 speechdelay -= multiplier;
4326 texupdatedelay -= multiplier;
4327 interestdelay -= multiplier;
4328 flamedelay -= multiplier;
4329 parriedrecently -= multiplier;
4331 victim = this->shared_from_this();
4336 speed = 1.1 * speedmult;
4338 speed = 1.0 * speedmult;
4340 rabbitkickragdoll = 0;
4344 if (id != 0 && (creature == rabbittype || difficulty != 2))
4346 if (id != 0 && creature == wolftype && difficulty == 2) {
4348 if (aitype != passivetype) {
4350 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) {
4356 if (animTarget == wolfrunninganim && !superruntoggle) {
4357 animTarget = getRun();
4361 if (weaponactive == -1 && num_weapons > 0) {
4362 if (weapons[weaponids[0]].getType() == staff) {
4368 burnt += multiplier;
4372 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4374 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4380 vel[0] = velocity.x;
4381 vel[1] = velocity.y;
4382 vel[2] = velocity.z;
4385 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4386 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4390 while (flamedelay < 0 && onfire) {
4392 int howmany = fabs(Random() % (skeleton.joints.size()));
4393 if (skeleton.free) {
4394 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4395 flatfacing = skeleton.joints[howmany].position * scale + coords;
4397 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4398 flatvelocity = (coords - oldcoords) / multiplier / 2;
4400 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4403 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4405 int howmany = fabs(Random() % (skeleton.joints.size()));
4406 if (skeleton.free) {
4407 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4408 flatfacing = skeleton.joints[howmany].position * scale + coords;
4410 flatvelocity = (coords - oldcoords) / multiplier / 2;
4411 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4413 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4417 bleeding -= multiplier * .3;
4418 if (bloodtoggle == 2) {
4419 skeleton.drawmodel.textureptr.bind();
4420 if ((bleeding <= 0) && (detail != 2))
4425 if (neckspurtamount > 0) {
4426 neckspurtamount -= multiplier;
4427 neckspurtdelay -= multiplier * 3;
4428 neckspurtparticledelay -= multiplier * 3;
4429 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4432 if (skeleton.free) {
4433 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4434 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4435 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4437 bloodvel.z = 5 * neckspurtamount;
4438 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4439 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4440 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4442 neckspurtparticledelay = .05;
4444 if (neckspurtdelay < 0) {
4449 if (deathbleeding > 0 && dead != 2) {
4450 if (deathbleeding < 5)
4451 bleeddelay -= deathbleeding * multiplier / 4;
4453 bleeddelay -= 5 * multiplier / 4;
4454 if (bleeddelay < 0 && bloodtoggle) {
4459 if (skeleton.free) {
4460 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4461 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4463 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4464 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4468 bloodloss += deathbleeding * multiplier * 80;
4469 deathbleeding -= multiplier * 1.6;
4470 if (deathbleeding < 0)
4472 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4473 if (weaponactive != -1) {
4474 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4475 weapons[weaponids[0]].velocity.x += .01;
4478 weaponids[0] = weaponids[num_weapons];
4479 if (weaponstuck == num_weapons)
4483 for (unsigned i = 0; i < Person::players.size(); i++) {
4484 Person::players[i]->wentforweapon = 0;
4492 if (!dead && creature == wolftype) {
4493 award_bonus(0, Wolfbonus);
4496 if (animTarget == knifefollowedanim && !skeleton.free) {
4497 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4498 skeleton.joints[i].velocity = 0;
4499 skeleton.joints[i].velocity.y = -2;
4502 if (id != 0 && unconscioustime > .1) {
4510 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4511 texupdatedelay = .12;
4513 bloodsize = 5 - realtexdetail;
4517 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4518 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4519 endx = startx + bloodsize;
4520 endy = starty + bloodsize;
4530 if (endx > skeleton.skinsize - 1) {
4531 endx = skeleton.skinsize - 1;
4534 if (endy > skeleton.skinsize - 1) {
4535 endy = skeleton.skinsize - 1;
4543 for (int i = startx; i < endx; i++) {
4544 for (int j = starty; j < endy; j++) {
4545 if (Random() % 2 == 0) {
4546 color = Random() % 85 + 170;
4547 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4548 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4549 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4550 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4555 skeleton.drawmodel.textureptr.bind();
4559 if (skeleton.free) {
4560 bleedx += 4 * direction / realtexdetail;
4562 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4564 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4566 bleedy -= 4 / realtexdetail;
4568 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4570 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4574 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4575 righthandmorphness = targetrighthandmorphness;
4576 righthandmorphstart = righthandmorphend;
4577 } else if (righthandmorphness > targetrighthandmorphness) {
4578 righthandmorphness -= multiplier * 4;
4579 } else if (righthandmorphness < targetrighthandmorphness) {
4580 righthandmorphness += multiplier * 4;
4583 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4584 lefthandmorphness = targetlefthandmorphness;
4585 lefthandmorphstart = lefthandmorphend;
4586 } else if (lefthandmorphness > targetlefthandmorphness) {
4587 lefthandmorphness -= multiplier * 4;
4588 } else if (lefthandmorphness < targetlefthandmorphness) {
4589 lefthandmorphness += multiplier * 4;
4592 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4593 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4594 tailmorphness = targettailmorphness;
4595 tailmorphstart = tailmorphend;
4596 } else if (tailmorphness > targettailmorphness) {
4597 tailmorphness -= multiplier * 10;
4598 } else if (tailmorphness < targettailmorphness) {
4599 tailmorphness += multiplier * 10;
4603 if (creature == wolftype) {
4604 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4605 tailmorphness = targettailmorphness;
4606 tailmorphstart = tailmorphend;
4607 } else if (tailmorphness > targettailmorphness) {
4608 tailmorphness -= multiplier * 2;
4609 } else if (tailmorphness < targettailmorphness) {
4610 tailmorphness += multiplier * 2;
4614 if (headmorphend == 3 || headmorphstart == 3) {
4615 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4616 headmorphness = targetheadmorphness;
4617 headmorphstart = headmorphend;
4618 } else if (headmorphness > targetheadmorphness) {
4619 headmorphness -= multiplier * 7;
4620 } else if (headmorphness < targetheadmorphness) {
4621 headmorphness += multiplier * 7;
4623 } else if (headmorphend == 5 || headmorphstart == 5) {
4624 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4625 headmorphness = targetheadmorphness;
4626 headmorphstart = headmorphend;
4627 } else if (headmorphness > targetheadmorphness) {
4628 headmorphness -= multiplier * 10;
4629 } else if (headmorphness < targetheadmorphness) {
4630 headmorphness += multiplier * 10;
4633 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4634 headmorphness = targetheadmorphness;
4635 headmorphstart = headmorphend;
4636 } else if (headmorphness > targetheadmorphness) {
4637 headmorphness -= multiplier * 4;
4638 } else if (headmorphness < targetheadmorphness) {
4639 headmorphness += multiplier * 4;
4643 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4644 chestmorphness = targetchestmorphness;
4645 chestmorphstart = chestmorphend;
4646 } else if (chestmorphness > targetchestmorphness) {
4647 chestmorphness -= multiplier;
4648 } else if (chestmorphness < targetchestmorphness) {
4649 chestmorphness += multiplier;
4652 if (dead != 2 && howactive <= typesleeping) {
4653 if (chestmorphstart == 0 && chestmorphend == 0) {
4655 targetchestmorphness = 1;
4658 if (chestmorphstart != 0 && chestmorphend != 0) {
4660 targetchestmorphness = 1;
4662 if (environment == snowyenvironment) {
4665 if (skeleton.free) {
4666 footvel = skeleton.specialforward[0] * -1;
4667 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4669 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4670 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4672 if (animTarget == sleepanim)
4673 footvel = DoRotation(footvel, 0, 90, 0);
4674 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4678 if (!dead && howactive < typesleeping) {
4679 blinkdelay -= multiplier * 2;
4680 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4682 targetheadmorphness = 1;
4684 blinkdelay = (float)(abs(Random() % 40)) / 5;
4686 if (headmorphstart == 3 && headmorphend == 3) {
4688 targetheadmorphness = 1;
4693 twitchdelay -= multiplier * 1.5;
4694 if (animTarget != hurtidleanim) {
4695 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4697 targetheadmorphness = 1;
4699 twitchdelay = (float)(abs(Random() % 40)) / 5;
4701 if (headmorphstart == 5 && headmorphend == 5) {
4703 targetheadmorphness = 1;
4707 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4708 twitchdelay3 -= multiplier * 1;
4709 if (Random() % 2 == 0) {
4710 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4711 righthandmorphness = 0;
4712 targetrighthandmorphness = 1;
4713 righthandmorphend = 1;
4714 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4716 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4717 righthandmorphness = 0;
4718 targetrighthandmorphness = 1;
4719 righthandmorphend = 0;
4722 if (Random() % 2 == 0) {
4723 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4724 lefthandmorphness = 0;
4725 targetlefthandmorphness = 1;
4726 lefthandmorphend = 1;
4727 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4729 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4730 lefthandmorphness = 0;
4731 targetlefthandmorphness = 1;
4732 lefthandmorphend = 0;
4738 if (creature == rabbittype) {
4739 if (howactive < typesleeping)
4740 twitchdelay2 -= multiplier * 1.5;
4742 twitchdelay2 -= multiplier * 0.5;
4743 if (howactive <= typesleeping) {
4744 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4746 targettailmorphness = 1;
4748 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4750 if (tailmorphstart == 1 && tailmorphend == 1) {
4752 targettailmorphness = 1;
4755 if (tailmorphstart == 2 && tailmorphend == 2) {
4757 targettailmorphness = 1;
4764 if (creature == wolftype) {
4765 twitchdelay2 -= multiplier * 1.5;
4766 if (tailmorphend != 0)
4767 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4769 targettailmorphness = 1;
4773 if (tailmorphend != 5)
4774 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4776 targettailmorphness = 1;
4780 if (twitchdelay2 <= 0) {
4781 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4783 targettailmorphness = 1;
4786 if (tailmorphstart == 1 && tailmorphend == 1) {
4788 targettailmorphness = 1;
4791 if (tailmorphstart == 2 && tailmorphend == 2) {
4793 targettailmorphness = 1;
4796 if (tailmorphstart == 3 && tailmorphend == 3) {
4798 targettailmorphness = 1;
4801 if (tailmorphstart == 4 && tailmorphend == 4) {
4803 targettailmorphness = 1;
4810 unconscioustime = 0;
4813 if (dead == 1 || howactive == typesleeping) {
4814 unconscioustime += multiplier;
4815 //If unconscious, close eyes and mouth
4816 if (righthandmorphend != 0)
4817 righthandmorphness = 0;
4818 righthandmorphend = 0;
4819 targetrighthandmorphness = 1;
4821 if (lefthandmorphend != 0)
4822 lefthandmorphness = 0;
4823 lefthandmorphend = 0;
4824 targetlefthandmorphness = 1;
4826 if (headmorphend != 3 && headmorphend != 5)
4829 targetheadmorphness = 1;
4833 if (howactive > typesleeping) {
4836 if (bloodtoggle && !bled) {
4837 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4839 if (bloodtoggle && !bled)
4840 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4841 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4842 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4846 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4851 if (dead == 2 || howactive > typesleeping) {
4852 //If dead, open mouth and hands
4853 if (righthandmorphend != 0)
4854 righthandmorphness = 0;
4855 righthandmorphend = 0;
4856 targetrighthandmorphness = 1;
4858 if (lefthandmorphend != 0)
4859 lefthandmorphness = 0;
4860 lefthandmorphend = 0;
4861 targetlefthandmorphness = 1;
4863 if (headmorphend != 2)
4866 targetheadmorphness = 1;
4869 if (stunned > 0 && !dead && headmorphend != 2) {
4870 if (headmorphend != 4)
4873 targetheadmorphness = 1;
4876 if (damage > damagetolerance && !dead) {
4879 unconscioustime = 0;
4881 if (creature == wolftype) {
4882 award_bonus(0, Wolfbonus);
4887 if (weaponactive != -1) {
4888 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4889 weapons[weaponids[0]].velocity.x += .01;
4892 weaponids[0] = weaponids[num_weapons];
4893 if (weaponstuck == num_weapons)
4897 for (unsigned i = 0; i < Person::players.size(); i++) {
4898 Person::players[i]->wentforweapon = 0;
4904 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4913 damage -= multiplier * 13;
4914 permanentdamage -= multiplier * 4;
4915 if (isIdle() || isCrouch()) {
4916 permanentdamage -= multiplier * 4;
4921 if (permanentdamage < 0)
4922 permanentdamage = 0;
4923 if (superpermanentdamage < 0)
4924 superpermanentdamage = 0;
4925 if (permanentdamage < superpermanentdamage) {
4926 permanentdamage = superpermanentdamage;
4928 if (damage < permanentdamage) {
4929 damage = permanentdamage;
4931 if (dead == 1 && damage < damagetolerance) {
4935 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4936 skeleton.joints[i].velocity = 0;
4939 if (permanentdamage > damagetolerance && dead != 2) {
4942 if (weaponactive != -1) {
4943 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4944 weapons[weaponids[0]].velocity.x += .01;
4947 weaponids[0] = weaponids[num_weapons];
4948 if (weaponstuck == num_weapons)
4952 for (unsigned i = 0; i < Person::players.size(); i++) {
4953 Person::players[i]->wentforweapon = 0;
4959 if (!dead && creature == wolftype) {
4960 award_bonus(0, Wolfbonus);
4963 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4964 award_bonus(id, touchofdeath);
4965 if (id != 0 && unconscioustime > .1) {
4973 emit_sound_at(breaksound, coords);
4976 if (skeleton.free == 1) {
4978 pause_sound(whooshsound);
4981 //If knocked over, open hands and close mouth
4982 if (righthandmorphend != 0)
4983 righthandmorphness = 0;
4984 righthandmorphend = 0;
4985 targetrighthandmorphness = 1;
4987 if (lefthandmorphend != 0)
4988 lefthandmorphness = 0;
4989 lefthandmorphend = 0;
4990 targetlefthandmorphness = 1;
4992 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4993 if (headmorphend != 0)
4996 targetheadmorphness = 1;
5000 skeleton.DoGravity(&scale);
5002 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5003 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
5004 award_bonus(id, deepimpact);
5005 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5009 if (!skeleton.joints.empty()) {
5010 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5011 average += skeleton.joints[j].position;
5013 average /= skeleton.joints.size();
5014 coords += average * scale;
5015 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5016 skeleton.joints[j].position -= average;
5018 average /= multiplier;
5022 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5023 velocity += skeleton.joints[i].velocity * scale;
5025 velocity /= skeleton.joints.size();
5027 if (!isnormal(velocity.x) && velocity.x) {
5031 if (findLength(&average) < 10 && dead && skeleton.free) {
5032 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5033 if (skeleton.longdead > 2000) {
5034 if (skeleton.longdead > 6000) {
5036 pause_sound(whooshsound);
5041 if (dead == 2 && bloodloss < damagetolerance) {
5043 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5045 if (bloodtoggle && !bled) {
5046 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5048 if (bloodtoggle && !bled)
5049 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5050 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5051 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5052 float size = .2 * 1.2;
5055 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5059 if (dead == 2 && bloodloss >= damagetolerance) {
5061 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5064 if (bloodtoggle && !bled) {
5065 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5067 if (bloodtoggle && !bled)
5068 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5069 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5070 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5074 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5081 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5082 bool canrecover = 1;
5083 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5084 startpoint = coords;
5087 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5089 if (velocity.y < -30)
5091 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5092 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5093 colviewer = startpoint;
5094 coltarget = endpoint;
5095 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5104 terrainnormal = jointPos(groin) - jointPos(abdomen);
5105 if (joint(groin).locked && joint(abdomen).locked) {
5106 terrainnormal = jointPos(groin) - jointPos(abdomen);
5107 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5109 if (joint(abdomen).locked && joint(neck).locked) {
5110 terrainnormal = jointPos(abdomen) - jointPos(neck);
5111 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5113 if (joint(groin).locked && joint(neck).locked) {
5114 terrainnormal = jointPos(groin) - jointPos(neck);
5115 middle = (jointPos(groin) + jointPos(neck)) / 2;
5117 Normalise(&terrainnormal);
5119 targetyaw = -asin(0 - terrainnormal.x);
5120 targetyaw *= 360 / 6.28;
5121 if (terrainnormal.z < 0)
5122 targetyaw = 180 - targetyaw;
5126 animTarget = flipanim;
5127 crouchtogglekeydown = 1;
5132 animCurrent = tempanim;
5136 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5137 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5138 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5143 if (findLength(&average) < 10 && !dead && skeleton.free) {
5144 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5145 if (skeleton.longdead > (damage + 500) * 1.5) {
5147 pause_sound(whooshsound);
5153 terrainnormal = jointPos(groin) - jointPos(abdomen);
5154 if (joint(groin).locked && joint(abdomen).locked) {
5155 terrainnormal = jointPos(groin) - jointPos(abdomen);
5156 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5158 if (joint(abdomen).locked && joint(neck).locked) {
5159 terrainnormal = jointPos(abdomen) - jointPos(neck);
5160 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5162 if (joint(groin).locked && joint(neck).locked) {
5163 terrainnormal = jointPos(groin) - jointPos(neck);
5164 middle = (jointPos(groin) + jointPos(neck)) / 2;
5166 Normalise(&terrainnormal);
5168 targetyaw = -asin(0 - terrainnormal.x);
5169 targetyaw *= 360 / 6.28;
5170 if (terrainnormal.z < 0)
5171 targetyaw = 180 - targetyaw;
5174 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5177 if (skeleton.forward.y < 0) {
5178 animTarget = getupfrombackanim;
5182 if (skeleton.forward.y > -.3) {
5183 animTarget = getupfromfrontanim;
5191 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5192 animTarget = rollanim;
5193 targetyaw = lookyaw;
5210 if ( !leftkeydown && !rightkeydown)
5217 if (abs(targettilt2) > 50)
5219 animCurrent = tempanim;
5222 tilt2 = targettilt2;
5224 if (middle.y > 0 && animTarget != rollanim)
5225 targetoffset.y = middle.y + 1;
5227 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5228 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5229 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5236 if (num_weapons > 0)
5237 if (weapons[0].getType() == staff)
5239 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5240 if (velocity.y > -30) {
5242 tempvelocity = velocity;
5243 Normalise(&tempvelocity);
5244 targetyaw = -asin(0 - tempvelocity.x);
5245 targetyaw *= 360 / 6.28;
5247 targetyaw = 180 - targetyaw;
5251 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5252 animTarget = rollanim;
5255 animTarget = backhandspringanim;
5261 emit_sound_at(movewhooshsound, coords, 128.);
5263 animCurrent = animTarget;
5264 frameCurrent = frameTarget - 1;
5276 if (skeleton.freefall == 0)
5281 if (aitype != passivetype || skeleton.free == 1)
5282 if (findLengthfast(&velocity) > .1)
5283 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5284 if (Object::objects[i]->type == firetype)
5285 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) {
5287 if (!Object::objects[i]->onfire) {
5288 emit_sound_at(firestartsound, Object::objects[i]->position);
5290 Object::objects[i]->onfire = 1;
5293 if (Object::objects[i]->onfire) {
5298 if (Object::objects[i]->type == bushtype)
5299 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) {
5301 if (!Object::objects[i]->onfire) {
5302 emit_sound_at(firestartsound, Object::objects[i]->position);
5304 Object::objects[i]->onfire = 1;
5308 if (Object::objects[i]->onfire) {
5312 if (Object::objects[i]->messedwith <= 0) {
5316 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5319 addEnvSound(coords, 4 * findLength(&velocity));
5323 if (environment == grassyenvironment)
5324 howmany = findLength(&velocity) * 4;
5325 if (environment == snowyenvironment)
5326 howmany = findLength(&velocity) * 2;
5328 if (environment != desertenvironment)
5329 for (int j = 0; j < howmany; j++) {
5330 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5331 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5332 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5335 pos.x += float(abs(Random() % 100) - 50) / 200;
5336 pos.y += float(abs(Random() % 100) - 50) / 200;
5337 pos.z += float(abs(Random() % 100) - 50) / 200;
5338 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);
5339 Sprite::setLastSpriteSpecial(1);
5341 howmany = findLength(&velocity) * 4;
5343 if (environment == snowyenvironment)
5344 for (int j = 0; j < howmany; j++) {
5345 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5346 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5347 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5350 pos.x += float(abs(Random() % 100) - 50) / 200;
5351 pos.y += float(abs(Random() % 100) - 50) / 200;
5352 pos.z += float(abs(Random() % 100) - 50) / 200;
5353 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5354 Sprite::setLastSpriteSpecial(2);
5357 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5358 Object::objects[i]->roty += velocity.z * multiplier * 6;
5359 Object::objects[i]->messedwith = .5;
5362 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5363 if (Object::objects[i]->pitch == 0)
5366 tempcoord = coords - Object::objects[i]->position;
5367 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5368 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5369 tempcoord += Object::objects[i]->position;
5371 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) {
5372 if (Object::objects[i]->messedwith <= 0) {
5376 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5379 addEnvSound(coords, 4 * findLength(&velocity));
5383 if (environment == grassyenvironment)
5384 howmany = findLength(&velocity) * 4;
5385 if (environment == snowyenvironment)
5386 howmany = findLength(&velocity) * 2;
5388 if (environment != desertenvironment)
5389 for (int j = 0; j < howmany; j++) {
5390 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5391 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5392 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5394 pos += velocity * .1;
5396 pos.x += float(abs(Random() % 100) - 50) / 150;
5397 pos.y += float(abs(Random() % 100) - 50) / 150;
5398 pos.z += float(abs(Random() % 100) - 50) / 150;
5399 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);
5400 Sprite::setLastSpriteSpecial(1);
5402 howmany = findLength(&velocity) * 4;
5404 if (environment == snowyenvironment)
5405 for (int j = 0; j < howmany; j++) {
5406 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5407 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5408 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5410 pos += velocity * .1;
5412 pos.x += float(abs(Random() % 100) - 50) / 150;
5413 pos.y += float(abs(Random() % 100) - 50) / 150;
5414 pos.z += float(abs(Random() % 100) - 50) / 150;
5415 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5416 Sprite::setLastSpriteSpecial(2);
5419 Object::objects[i]->messedwith = .5;
5424 if (!skeleton.free) {
5427 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5430 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5432 if (Tutorial::active && id != 0)
5434 if (play && aitype != playercontrolled) {
5435 int whichsound = -1;
5436 if (speechdelay <= 0) {
5437 unsigned int i = abs(Random() % 4);
5438 if (creature == rabbittype) {
5440 whichsound = rabbitchitter;
5442 whichsound = rabbitchitter2;
5444 if (creature == wolftype) {
5446 whichsound = growlsound;
5448 whichsound = growl2sound;
5453 if (whichsound != -1) {
5454 emit_sound_at(whichsound, coords);
5458 if (animTarget == staggerbackhighanim)
5460 if (animTarget == staggerbackhardanim)
5462 staggerdelay -= multiplier;
5463 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5465 if (velocity.y < -30 && animTarget == jumpdownanim)
5467 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5468 animTarget = getIdle();
5472 weaponmissdelay -= multiplier;
5473 highreversaldelay -= multiplier;
5474 lowreversaldelay -= multiplier;
5475 lastcollide -= multiplier;
5476 skiddelay -= multiplier;
5477 if (!isnormal(velocity.x) && velocity.x) {
5480 if (!isnormal(targettilt) && targettilt) {
5483 if (!isnormal(targettilt2) && targettilt2) {
5486 if (!isnormal(targetyaw) && targetyaw) {
5490 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5491 //open hands and close mouth
5492 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5493 righthandmorphness = 0;
5494 righthandmorphend = 0;
5495 targetrighthandmorphness = 1;
5498 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5499 lefthandmorphness = 0;
5500 lefthandmorphend = 0;
5501 targetlefthandmorphness = 1;
5504 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5507 targetheadmorphness = 1;
5511 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) {
5512 //open hands and mouth
5513 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5514 righthandmorphness = 0;
5515 righthandmorphend = 0;
5516 targetrighthandmorphness = 1;
5519 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5520 lefthandmorphness = 0;
5521 lefthandmorphend = 0;
5522 targetlefthandmorphness = 1;
5525 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5528 targetheadmorphness = 1;
5532 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5533 //close hands and mouth
5534 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5535 righthandmorphness = 0;
5536 righthandmorphend = 1;
5537 targetrighthandmorphness = 1;
5540 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5541 lefthandmorphness = 0;
5542 lefthandmorphend = 1;
5543 targetlefthandmorphness = 1;
5546 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5549 targetheadmorphness = 1;
5553 if (animTarget == spinkickanim ||
5554 animTarget == staffspinhitreversalanim ||
5555 animTarget == staffspinhitreversedanim ||
5556 animTarget == staffhitreversalanim ||
5557 animTarget == staffhitreversedanim ||
5558 animTarget == hurtidleanim ||
5559 animTarget == winduppunchanim ||
5560 animTarget == swordslashreversalanim ||
5561 animTarget == swordslashreversedanim ||
5562 animTarget == knifeslashreversalanim ||
5563 animTarget == knifeslashreversedanim ||
5564 animTarget == knifethrowanim ||
5565 animTarget == knifefollowanim ||
5566 animTarget == knifefollowedanim ||
5567 animTarget == killanim ||
5568 animTarget == dropkickanim ||
5569 animTarget == upunchanim ||
5570 animTarget == knifeslashstartanim ||
5571 animTarget == swordslashanim ||
5572 animTarget == staffhitanim ||
5573 animTarget == staffspinhitanim ||
5574 animTarget == staffgroundsmashanim ||
5575 animTarget == spinkickreversalanim ||
5576 animTarget == sweepreversalanim ||
5577 animTarget == lowkickanim ||
5578 animTarget == sweepreversedanim ||
5579 animTarget == rabbitkickreversalanim ||
5580 animTarget == rabbitkickreversedanim ||
5581 animTarget == jumpreversalanim ||
5582 animTarget == jumpreversedanim) {
5583 //close hands and yell
5584 if (righthandmorphend != 1 &&
5585 righthandmorphness == targetrighthandmorphness) {
5586 righthandmorphness = 0;
5587 righthandmorphend = 1;
5588 targetrighthandmorphness = 1;
5591 if (lefthandmorphend != 1 &&
5592 lefthandmorphness == targetlefthandmorphness) {
5593 lefthandmorphness = 0;
5594 lefthandmorphend = 1;
5595 targetlefthandmorphness = 1;
5598 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5601 targetheadmorphness = 1;
5608 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5609 (victim->aitype != searchtype) && (aitype != passivetype) &&
5610 (aitype != searchtype) && (victim->id < Person::players.size())) {
5611 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5615 if (!dead && animTarget != hurtidleanim)
5616 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5617 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5620 targetheadmorphness = 1;
5624 if (weaponactive != -1) {
5625 if (weapons[weaponids[weaponactive]].getType() != staff) {
5626 righthandmorphstart = 1;
5627 righthandmorphend = 1;
5629 if (weapons[weaponids[weaponactive]].getType() == staff) {
5630 righthandmorphstart = 2;
5631 righthandmorphend = 2;
5633 targetrighthandmorphness = 1;
5636 terrainnormal = terrain.getNormal(coords.x, coords.z);
5638 if (Animation::animations[animTarget].attack != reversal) {
5639 if (!isnormal(coords.x))
5647 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5648 facing = flatfacing;
5649 ReflectVector(&facing, terrainnormal);
5653 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5655 targettilt2 = -facing.y * 20;
5660 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5662 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5663 flatvelocity = velocity;
5665 flatvelspeed = findLength(&flatvelocity);
5666 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5667 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5672 if (targettilt > 25)
5674 if (targettilt < -25)
5678 if (targettilt2 > 45)
5680 if (targettilt2 < -45)
5682 if (abs(tilt2 - targettilt2) < multiplier * 400)
5683 tilt2 = targettilt2;
5684 else if (tilt2 > targettilt2) {
5685 tilt2 -= multiplier * 400;
5686 } else if (tilt2 < targettilt2) {
5687 tilt2 += multiplier * 400;
5689 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5696 if (!isnormal(targettilt) && targettilt) {
5699 if (!isnormal(targettilt2) && targettilt2) {
5704 if (animTarget == rabbittackleanim) {
5705 velocity += facing * multiplier * speed * 700 * scale;
5706 velspeed = findLength(&velocity);
5707 if (velspeed > speed * 65 * scale) {
5708 velocity /= velspeed;
5709 velspeed = speed * 65 * scale;
5710 velocity *= velspeed;
5712 velocity.y += gravity * multiplier * 20;
5713 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5714 velspeed = findLength(&velocity);
5715 velocity = flatfacing * velspeed;
5717 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5718 if (isRun() || animTarget == rabbitkickanim) {
5719 velocity += facing * multiplier * speed * 700 * scale;
5720 velspeed = findLength(&velocity);
5721 if (velspeed > speed * 45 * scale) {
5722 velocity /= velspeed;
5723 velspeed = speed * 45 * scale;
5724 velocity *= velspeed;
5726 velocity.y += gravity * multiplier * 20;
5727 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5728 velspeed = findLength(&velocity);
5729 if (velspeed < speed * 30 * scale)
5730 velspeed = speed * 30 * scale;
5731 velocity = flatfacing * velspeed;
5733 } else if (isRun()) {
5734 velocity += facing * multiplier * speed * 700 * scale;
5735 velspeed = findLength(&velocity);
5736 if (creature == rabbittype) {
5737 if (velspeed > speed * 55 * scale) {
5738 velocity /= velspeed;
5739 velspeed = speed * 55 * scale;
5740 velocity *= velspeed;
5743 if (creature == wolftype) {
5744 if (velspeed > speed * 75 * scale) {
5745 velocity /= velspeed;
5746 velspeed = speed * 75 * scale;
5747 velocity *= velspeed;
5750 velocity.y += gravity * multiplier * 20;
5751 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5752 velspeed = findLength(&velocity);
5753 velocity = flatfacing * velspeed;
5756 if (animTarget == rollanim && targetFrame().label != 6) {
5757 velocity += facing * multiplier * speed * 700 * scale;
5758 velspeed = findLength(&velocity);
5759 if (velspeed > speed * 45 * scale) {
5760 velocity /= velspeed;
5761 velspeed = speed * 45 * scale;
5762 velocity *= velspeed;
5764 velocity.y += gravity * multiplier * 20;
5765 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5766 velspeed = findLength(&velocity);
5767 velocity = flatfacing * velspeed;
5770 if (animTarget == sneakanim || animTarget == walkanim) {
5771 velocity += facing * multiplier * speed * 700 * scale;
5772 velspeed = findLength(&velocity);
5773 if (velspeed > speed * 12 * scale) {
5774 velocity /= velspeed;
5775 velspeed = speed * 12 * scale;
5776 velocity *= velspeed;
5778 velocity.y += gravity * multiplier * 20;
5779 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5780 velspeed = findLength(&velocity);
5781 velocity = flatfacing * velspeed;
5784 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5785 velocity += facing * multiplier * speed * 700 * scale;
5786 velspeed = findLength(&velocity);
5787 if (velspeed > speed * 2 * scale) {
5788 velocity /= velspeed;
5789 velspeed = speed * 2 * scale;
5790 velocity *= velspeed;
5792 velocity.y += gravity * multiplier * 20;
5793 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5794 velspeed = findLength(&velocity);
5795 velocity = flatfacing * velspeed;
5799 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5800 velocity -= facing * multiplier * speed * 700 * scale;
5801 velspeed = findLength(&velocity);
5802 if (velspeed > speed * 2 * scale) {
5803 velocity /= velspeed;
5804 velspeed = speed * 2 * scale;
5805 velocity *= velspeed;
5807 velocity.y += gravity * multiplier * 20;
5808 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5809 velspeed = findLength(&velocity);
5810 velocity = flatfacing * velspeed * -1;
5813 if (animTarget == fightsidestep) {
5814 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5815 velspeed = findLength(&velocity);
5816 if (velspeed > speed * 12 * scale) {
5817 velocity /= velspeed;
5818 velspeed = speed * 12 * scale;
5819 velocity *= velspeed;
5821 velocity.y += gravity * multiplier * 20;
5822 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5823 velspeed = findLength(&velocity);
5824 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5827 if (animTarget == staggerbackhighanim) {
5828 coords -= facing * multiplier * speed * 16 * scale;
5831 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5832 coords -= facing * multiplier * speed * 20 * scale;
5836 if (animTarget == backhandspringanim) {
5837 //coords-=facing*multiplier*50*scale;
5838 velocity += facing * multiplier * speed * 700 * scale * -1;
5839 velspeed = findLength(&velocity);
5840 if (velspeed > speed * 50 * scale) {
5841 velocity /= velspeed;
5842 velspeed = speed * 50 * scale;
5843 velocity *= velspeed;
5845 velocity.y += gravity * multiplier * 20;
5846 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5847 velspeed = findLength(&velocity);
5848 velocity = flatfacing * velspeed * -1;
5850 if (animTarget == dodgebackanim) {
5851 //coords-=facing*multiplier*50*scale;
5852 velocity += facing * multiplier * speed * 700 * scale * -1;
5853 velspeed = findLength(&velocity);
5854 if (velspeed > speed * 60 * scale) {
5855 velocity /= velspeed;
5856 velspeed = speed * 60 * scale;
5857 velocity *= velspeed;
5859 velocity.y += gravity * multiplier * 20;
5860 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5861 velspeed = findLength(&velocity);
5862 velocity = flatfacing * velspeed * -1;
5865 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5866 velspeed = findLength(&velocity);
5870 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5871 velocity.y += gravity * multiplier;
5874 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5875 coords += velocity * multiplier;
5877 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5878 if (isFlip() && targetFrame().label == 7)
5881 if (animTarget == jumpupanim) {
5883 animTarget = getIdle();
5890 pause_sound(whooshsound);
5891 OPENAL_SetVolume(channels[whooshsound], 0);
5894 if (animTarget == jumpdownanim || isFlip()) {
5895 if (isFlip())jumppower = -4;
5896 animTarget = getLanding();
5897 emit_sound_at(landsound, coords, 128.);
5900 addEnvSound(coords);
5905 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5906 coords.y += gravity * multiplier * 2;
5907 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5908 coords.y = terrain.getHeight(coords.x, coords.z);
5913 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)) {
5914 velspeed = findLength(&velocity);
5916 if (velspeed < multiplier * 300 * scale) {
5919 velocity -= velocity / velspeed * multiplier * 300 * scale;
5921 if (velspeed > 5 && (isLanding() || isLandhard())) {
5922 skiddingdelay += multiplier;
5923 if (skiddelay <= 0) {
5924 FootLand(leftfoot, .5);
5925 FootLand(rightfoot, .5);
5934 velspeed = findLength(&velocity);
5936 if (velspeed > 5 && (isLanding() || isLandhard())) {
5937 skiddingdelay += multiplier;
5938 if (skiddelay <= 0) {
5939 FootLand(leftfoot, .5);
5940 FootLand(rightfoot, .5);
5948 if (skiddingdelay < 0)
5949 skiddingdelay += multiplier;
5950 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5952 if (!onterrain || environment == grassyenvironment) {
5953 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5955 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5959 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5960 terrainnormal = victim->coords - coords;
5961 Normalise(&terrainnormal);
5962 targetyaw = -asin(0 - terrainnormal.x);
5963 targetyaw *= 360 / 6.28;
5964 if (terrainnormal.z < 0)
5965 targetyaw = 180 - targetyaw;
5966 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5969 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5970 targetyaw = victim->targetyaw;
5972 if (animTarget == rabbittacklinganim) {
5973 coords = victim->coords;
5976 skeleton.oldfree = skeleton.free;
5980 midterrain.x = terrain.size * terrain.scale / 2;
5981 midterrain.z = terrain.size * terrain.scale / 2;
5982 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5984 tempposit = coords - midterrain;
5986 Normalise(&tempposit);
5987 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5988 coords.x = tempposit.x + midterrain.x;
5989 coords.z = tempposit.z + midterrain.z;
5995 * inverse kinematics helper function
5997 void IKHelper(Person *p, float interp)
5999 XYZ point, change, change2;
6000 float heightleft, heightright;
6002 // TODO: implement localToWorld and worldToLocal
6003 // but keep in mind it won't be the same math if player is ragdolled or something
6004 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6005 // then comb through code for places where to use it
6007 // point = localToWorld(jointPos(leftfoot))
6008 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6009 // adjust height of foot
6010 heightleft = terrain.getHeight(point.x, point.z) + .04;
6011 point.y = heightleft;
6012 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6013 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6014 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6015 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6016 // move ankle along with foot
6017 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6018 // average knee pos between old and new pos
6019 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6021 // do same as above for right leg
6022 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6023 heightright = terrain.getHeight(point.x, point.z) + .04;
6024 point.y = heightright;
6025 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6026 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6027 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6028 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6029 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6031 // fix up skeleton now that we've moved body parts?
6032 p->skeleton.DoConstraints(&p->coords, &p->scale);
6039 int Person::DrawSkeleton()
6041 int oldplayerdetail;
6042 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6043 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6053 glAlphaFunc(GL_GREATER, 0.0001);
6055 float terrainheight;
6059 if (!isnormal(tilt))
6061 if (!isnormal(tilt2))
6063 oldplayerdetail = playerdetail;
6065 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6068 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6071 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6076 if (playerdetail != oldplayerdetail) {
6078 normalsupdatedelay = 0;
6080 static float updatedelaychange;
6081 static float morphness;
6082 static float framemult;
6084 skeleton.FindForwards();
6085 if (howactive == typesittingwall) {
6086 skeleton.specialforward[1] = 0;
6087 skeleton.specialforward[1].z = 1;
6093 static int weaponattachmuscle;
6094 static int weaponrotatemuscle;
6095 static XYZ weaponpoint;
6096 static int start, endthing;
6097 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6098 if (!isSleeping() && !isSitting()) {
6099 // TODO: give these meaningful names
6100 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6101 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6102 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6103 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6105 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6107 if (creature == wolftype)
6111 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6112 IKHelper(this, target);
6113 if (creature == wolftype)
6114 IKHelper(this, target);
6117 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6118 IKHelper(this, 1 - target);
6119 if (creature == wolftype)
6120 IKHelper(this, 1 - target);
6124 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()))
6127 targetheadyaw = -targetyaw;
6128 targetheadpitch = 0;
6129 if (Animation::animations[animTarget].attack == 3)
6130 targetheadyaw += 180;
6132 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6133 skeleton.drawmodel.vertex[i] = 0;
6134 skeleton.drawmodel.vertex[i].y = 999;
6136 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6137 skeleton.drawmodellow.vertex[i] = 0;
6138 skeleton.drawmodellow.vertex[i].y = 999;
6140 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6141 skeleton.drawmodelclothes.vertex[i] = 0;
6142 skeleton.drawmodelclothes.vertex[i].y = 999;
6144 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
6145 // convenience renames
6146 const int p1 = skeleton.muscles[i].parent1->label;
6147 const int p2 = skeleton.muscles[i].parent2->label;
6149 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6154 if (p1 == righthand || p2 == righthand) {
6155 morphness = righthandmorphness;
6156 start = righthandmorphstart;
6157 endthing = righthandmorphend;
6159 if (p1 == lefthand || p2 == lefthand) {
6160 morphness = lefthandmorphness;
6161 start = lefthandmorphstart;
6162 endthing = lefthandmorphend;
6164 if (p1 == head || p2 == head) {
6165 morphness = headmorphness;
6166 start = headmorphstart;
6167 endthing = headmorphend;
6169 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6170 morphness = chestmorphness;
6171 start = chestmorphstart;
6172 endthing = chestmorphend;
6174 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6175 morphness = tailmorphness;
6176 start = tailmorphstart;
6177 endthing = tailmorphend;
6180 skeleton.FindRotationMuscle(i, animTarget);
6181 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6182 glMatrixMode(GL_MODELVIEW);
6186 glRotatef(tilt2, 1, 0, 0);
6188 glRotatef(tilt, 0, 0, 1);
6191 glTranslatef(mid.x, mid.y, mid.z);
6193 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6194 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6196 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6197 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6199 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6200 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6202 if (playerdetail || skeleton.free == 3) {
6203 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6204 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6205 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6206 glMatrixMode(GL_MODELVIEW);
6208 if (p1 == abdomen || p2 == abdomen)
6209 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6210 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6211 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6212 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6213 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6214 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6215 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6216 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6217 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6218 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6219 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6220 if (p1 == head || p2 == head)
6221 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6222 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6223 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6224 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6225 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6226 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6227 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6231 if (!playerdetail || skeleton.free == 3) {
6232 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6233 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6234 glMatrixMode(GL_MODELVIEW);
6236 if (p1 == abdomen || p2 == abdomen)
6237 glTranslatef(v0.x * proportionbody.x,
6238 v0.y * proportionbody.y,
6239 v0.z * proportionbody.z);
6240 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6241 glTranslatef(v0.x * proportionarms.x,
6242 v0.y * proportionarms.y,
6243 v0.z * proportionarms.z);
6244 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6245 glTranslatef(v0.x * proportionlegs.x,
6246 v0.y * proportionlegs.y,
6247 v0.z * proportionlegs.z);
6248 if (p1 == head || p2 == head)
6249 glTranslatef(v0.x * proportionhead.x,
6250 v0.y * proportionhead.y,
6251 v0.z * proportionhead.z);
6253 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6254 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6255 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6256 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6262 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6263 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6265 glMatrixMode(GL_MODELVIEW);
6269 glRotatef(tilt2, 1, 0, 0);
6271 glRotatef(tilt, 0, 0, 1);
6272 glTranslatef(mid.x, mid.y, mid.z);
6273 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6274 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6276 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6277 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6279 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6280 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6282 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6283 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6284 glMatrixMode(GL_MODELVIEW);
6286 if (p1 == abdomen || p2 == abdomen)
6287 glTranslatef(v0.x * proportionbody.x,
6288 v0.y * proportionbody.y,
6289 v0.z * proportionbody.z);
6290 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6291 glTranslatef(v0.x * proportionarms.x,
6292 v0.y * proportionarms.y,
6293 v0.z * proportionarms.z);
6294 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6295 glTranslatef(v0.x * proportionlegs.x,
6296 v0.y * proportionlegs.y,
6297 v0.z * proportionlegs.z);
6298 if (p1 == head || p2 == head)
6299 glTranslatef(v0.x * proportionhead.x,
6300 v0.y * proportionhead.y,
6301 v0.z * proportionhead.z);
6302 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6303 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6304 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6305 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6310 updatedelay = 1 + (float)(Random() % 100) / 1000;
6312 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6313 normalsupdatedelay = 1;
6314 if (playerdetail || skeleton.free == 3)
6315 skeleton.drawmodel.CalculateNormals(0);
6316 if (!playerdetail || skeleton.free == 3)
6317 skeleton.drawmodellow.CalculateNormals(0);
6318 if (skeleton.clothes)
6319 skeleton.drawmodelclothes.CalculateNormals(0);
6321 if (playerdetail || skeleton.free == 3)
6322 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6323 if (!playerdetail || skeleton.free == 3)
6324 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6325 if (skeleton.clothes) {
6326 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6331 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6332 if (updatedelaychange > -realmultiplier * 30)
6333 updatedelaychange = -realmultiplier * 30;
6334 if (updatedelaychange > -framemult * 4)
6335 updatedelaychange = -framemult * 4;
6336 if (skeleton.free == 1)
6337 updatedelaychange *= 6;
6339 updatedelaychange *= 8;
6340 updatedelay += updatedelaychange;
6342 glMatrixMode(GL_MODELVIEW);
6344 glTranslatef(coords.x, coords.y - .02, coords.z);
6345 if (!skeleton.free) {
6346 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6347 glRotatef(yaw, 0, 1, 0);
6351 glColor4f(.4, 1, .4, 1);
6352 glDisable(GL_LIGHTING);
6353 glDisable(GL_TEXTURE_2D);
6356 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6357 XYZ &v0 = skeleton.drawmodel.vertex[i];
6358 glVertex3f(v0.x, v0.y, v0.z);
6364 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6365 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6366 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6367 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6368 glVertex3f(v0.x, v0.y, v0.z);
6369 glVertex3f(v1.x, v1.y, v1.z);
6370 glVertex3f(v1.x, v1.y, v1.z);
6371 glVertex3f(v2.x, v2.y, v2.z);
6372 glVertex3f(v2.x, v2.y, v2.z);
6373 glVertex3f(v0.x, v0.y, v0.z);
6379 terrainlight = terrain.getLighting(coords.x, coords.z);
6380 distance = distsq(&viewer, &coords);
6381 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6385 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6386 if (terrainheight < 1)
6388 if (terrainheight > 1.7)
6389 terrainheight = 1.7;
6391 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6392 glDisable(GL_BLEND);
6393 glAlphaFunc(GL_GREATER, 0.0001);
6394 glEnable(GL_TEXTURE_2D);
6396 glDisable(GL_TEXTURE_2D);
6397 glColor4f(.7, .35, 0, .5);
6399 glEnable(GL_LIGHTING);
6402 if (Tutorial::active && id != 0) {
6403 glColor4f(.7, .7, .7, 0.6);
6405 glEnable(GL_LIGHTING);
6407 if (canattack && cananger)
6408 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6409 glDisable(GL_TEXTURE_2D);
6410 glColor4f(1, 0, 0, 0.8);
6412 glMatrixMode(GL_TEXTURE);
6414 glTranslatef(0, -smoketex, 0);
6415 glTranslatef(-smoketex, 0, 0);
6419 if (Tutorial::active && (id != 0))
6420 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6422 skeleton.drawmodel.draw();
6425 if (!playerdetail) {
6426 if (Tutorial::active && (id != 0))
6427 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6429 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6432 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6433 if (Tutorial::active && id != 0) {
6435 glMatrixMode(GL_MODELVIEW);
6436 glEnable(GL_TEXTURE_2D);
6437 glColor4f(.7, .7, .7, 0.6);
6439 glEnable(GL_LIGHTING);
6441 if (canattack && cananger)
6442 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6443 glDisable(GL_TEXTURE_2D);
6444 glColor4f(1, 0, 0, 0.8);
6446 glMatrixMode(GL_TEXTURE);
6448 glTranslatef(0, -smoketex * .6, 0);
6449 glTranslatef(smoketex * .6, 0, 0);
6452 if (Tutorial::active && (id != 0))
6453 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6455 skeleton.drawmodel.draw();
6458 if (!playerdetail) {
6459 if (Tutorial::active && (id != 0))
6460 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6462 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6467 if (Tutorial::active && id != 0) {
6469 glMatrixMode(GL_MODELVIEW);
6470 glEnable(GL_TEXTURE_2D);
6472 if (skeleton.clothes) {
6476 skeleton.drawmodelclothes.draw();
6478 skeleton.drawmodelclothes.drawimmediate();
6484 if (num_weapons > 0) {
6485 for (k = 0; k < num_weapons; k++) {
6487 if (weaponactive == k) {
6488 if (weapons[i].getType() != staff) {
6489 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6490 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6491 weaponattachmuscle = j;
6494 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6495 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) {
6496 weaponrotatemuscle = j;
6499 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6500 if (creature == wolftype)
6501 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6503 if (weapons[i].getType() == staff) {
6504 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6505 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6506 weaponattachmuscle = j;
6509 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6510 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) {
6511 weaponrotatemuscle = j;
6514 //weaponpoint=jointPos(rightwrist);
6515 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6516 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6517 XYZ tempnormthing, vec1, vec2;
6518 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6519 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6520 CrossProduct(&vec1, &vec2, &tempnormthing);
6521 Normalise(&tempnormthing);
6522 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6523 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6526 if (weaponactive != k && weaponstuck != k) {
6527 if (weapons[i].getType() == knife)
6528 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6529 if (weapons[i].getType() == sword)
6530 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6531 if (weapons[i].getType() == staff)
6532 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6533 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6534 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) {
6535 weaponrotatemuscle = j;
6539 if (weaponstuck == k) {
6540 if (weaponstuckwhere == 0)
6541 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6543 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6544 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6545 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) {
6546 weaponrotatemuscle = j;
6550 if (skeleton.free) {
6551 weapons[i].position = weaponpoint * scale + coords;
6552 weapons[i].bigrotation = 0;
6553 weapons[i].bigtilt = 0;
6554 weapons[i].bigtilt2 = 0;
6556 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;
6557 weapons[i].bigrotation = yaw;
6558 weapons[i].bigtilt = tilt;
6559 weapons[i].bigtilt2 = tilt2;
6561 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6562 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6563 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6564 if (weaponactive == k) {
6565 if (weapons[i].getType() == knife) {
6566 weapons[i].smallrotation = 180;
6567 weapons[i].smallrotation2 = 0;
6568 if (isCrouch() || wasCrouch()) {
6569 weapons[i].smallrotation2 = 20;
6571 if (animTarget == hurtidleanim) {
6572 weapons[i].smallrotation2 = 50;
6574 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6575 XYZ temppoint1, temppoint2;
6578 temppoint1 = jointPos(righthand);
6579 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6580 distance = findDistance(&temppoint1, &temppoint2);
6581 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6582 weapons[i].rotation2 *= 360 / 6.28;
6585 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6586 weapons[i].rotation1 *= 360 / 6.28;
6587 weapons[i].rotation3 = 0;
6588 weapons[i].smallrotation = -90;
6589 weapons[i].smallrotation2 = 0;
6590 if (temppoint1.x > temppoint2.x)
6591 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6593 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6594 XYZ temppoint1, temppoint2;
6597 temppoint1 = jointPos(righthand);
6598 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6599 distance = findDistance(&temppoint1, &temppoint2);
6600 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6601 weapons[i].rotation2 *= 360 / 6.28;
6604 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6605 weapons[i].rotation1 *= 360 / 6.28;
6606 weapons[i].rotation3 = 0;
6607 weapons[i].smallrotation = 90;
6608 weapons[i].smallrotation2 = 0;
6609 if (temppoint1.x > temppoint2.x)
6610 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6612 if (animTarget == knifethrowanim) {
6613 weapons[i].smallrotation = 90;
6614 //weapons[i].smallrotation2=-90;
6615 weapons[i].smallrotation2 = 0;
6616 weapons[i].rotation1 = 0;
6617 weapons[i].rotation2 = 0;
6618 weapons[i].rotation3 = 0;
6620 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6621 weapons[i].smallrotation = -90;
6622 weapons[i].rotation1 = 0;
6623 weapons[i].rotation2 = 0;
6624 weapons[i].rotation3 = 0;
6627 if (weapons[i].getType() == sword) {
6628 weapons[i].smallrotation = 0;
6629 weapons[i].smallrotation2 = 0;
6630 if (animTarget == knifethrowanim) {
6631 weapons[i].smallrotation = -90;
6632 weapons[i].smallrotation2 = 0;
6633 weapons[i].rotation1 = 0;
6634 weapons[i].rotation2 = 0;
6635 weapons[i].rotation3 = 0;
6637 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)) {
6638 XYZ temppoint1, temppoint2;
6641 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6642 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6643 distance = findDistance(&temppoint1, &temppoint2);
6644 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6645 weapons[i].rotation2 *= 360 / 6.28;
6648 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6649 weapons[i].rotation1 *= 360 / 6.28;
6650 weapons[i].rotation3 = 0;
6651 weapons[i].smallrotation = 90;
6652 weapons[i].smallrotation2 = 0;
6653 if (temppoint1.x > temppoint2.x)
6654 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6657 if (weapons[i].getType() == staff) {
6658 weapons[i].smallrotation = 100;
6659 weapons[i].smallrotation2 = 0;
6660 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6661 XYZ temppoint1, temppoint2;
6664 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6665 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6666 distance = findDistance(&temppoint1, &temppoint2);
6667 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6668 weapons[i].rotation2 *= 360 / 6.28;
6671 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6672 weapons[i].rotation1 *= 360 / 6.28;
6673 weapons[i].rotation3 = 0;
6674 weapons[i].smallrotation = 90;
6675 weapons[i].smallrotation2 = 0;
6676 if (temppoint1.x > temppoint2.x)
6677 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6681 if (weaponactive != k && weaponstuck != k) {
6682 if (weapons[i].getType() == knife) {
6683 weapons[i].smallrotation = -70;
6684 weapons[i].smallrotation2 = 10;
6686 if (weapons[i].getType() == sword) {
6687 weapons[i].smallrotation = -100;
6688 weapons[i].smallrotation2 = -8;
6690 if (weapons[i].getType() == staff) {
6691 weapons[i].smallrotation = -100;
6692 weapons[i].smallrotation2 = -8;
6695 if (weaponstuck == k) {
6696 if (weaponstuckwhere == 0)
6697 weapons[i].smallrotation = 180;
6699 weapons[i].smallrotation = 0;
6700 weapons[i].smallrotation2 = 10;
6709 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6711 if (animCurrent != animTarget)
6713 if (skeleton.free == 2)
6722 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6725 static float distance;
6726 static float olddistance;
6727 static int intersecting;
6728 static int firstintersecting;
6731 static XYZ start, end;
6732 static float slopethreshold = -.4;
6734 firstintersecting = -1;
6738 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6741 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6742 for (i = 0; i < 4; i++) {
6743 for (j = 0; j < model->TriangleNum; j++) {
6744 if (model->facenormals[j].y <= slopethreshold) {
6746 distance = abs((model->facenormals[j].x * p1->x) + (model->facenormals[j].y * p1->y) + (model->facenormals[j].z * p1->z) - ((model->facenormals[j].x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->facenormals[j].y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->facenormals[j].z * model->vertex[model->Triangles[j].vertex[0]].z)));
6747 if (distance < radius) {
6748 point = *p1 - model->facenormals[j] * distance;
6749 if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))
6752 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6753 &model->vertex[model->Triangles[j].vertex[1]],
6756 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6757 &model->vertex[model->Triangles[j].vertex[2]],
6760 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6761 &model->vertex[model->Triangles[j].vertex[2]],
6764 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6768 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->facenormals[j], &point)) {
6769 p1->y = point.y + radius;
6770 if ((animTarget == jumpdownanim || isFlip())) {
6771 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6774 if (animTarget == jumpupanim) {
6776 animTarget = getIdle();
6783 pause_sound(whooshsound);
6784 OPENAL_SetVolume(channels[whooshsound], 0);
6787 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6790 animTarget = getLanding();
6791 emit_sound_at(landsound, coords, 128.);
6794 addEnvSound(coords);
6801 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6802 olddistance = distance;
6803 firstintersecting = j;
6808 for (j = 0; j < model->TriangleNum; j++) {
6809 if (model->facenormals[j].y > slopethreshold) {
6812 start.y -= radius / 4;
6813 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6814 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6815 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6816 distance = abs((model->facenormals[j].x * start.x)
6817 + (model->facenormals[j].y * start.y)
6818 + (model->facenormals[j].z * start.z)
6819 - ((model->facenormals[j].x * v0.x)
6820 + (model->facenormals[j].y * v0.y)
6821 + (model->facenormals[j].z * v0.z)));
6822 if (distance < radius * .5) {
6823 point = start - model->facenormals[j] * distance;
6824 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6827 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6829 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6831 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6833 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6834 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6836 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6837 if (findLengthfast(&start) < findLengthfast(&velocity))
6840 *p1 += model->facenormals[j] * (distance - radius * .5);
6843 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6844 olddistance = distance;
6845 firstintersecting = j;
6852 *p = DoRotation(*p, 0, *rotate, 0);
6855 *p1 = DoRotation(*p1, 0, *rotate, 0);
6857 return firstintersecting;
6860 int findPathDist(int start, int end)
6865 unsigned int smallestcount = 1000;
6866 for (char i = 0; i < 50; i++) {
6867 unsigned int count = 0;
6872 while (last != end && count < 30) {
6874 for (int j = 0; j < Game::numpathpoints; j++) {
6875 if (j != last && j != last2 && j != last3 && j != last4) {
6877 if (Game::numpathpointconnect[j])
6878 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6879 if (Game::pathpointconnect[j][k] == last)connected = 1;
6882 if (Game::numpathpointconnect[last])
6883 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
6884 if (Game::pathpointconnect[last][k] == j)connected = 1;
6887 if (closest == -1 || Random() % 2 == 0) {
6898 if (count < smallestcount) {
6899 smallestcount = count;
6902 return smallestcount;
6905 void Person::takeWeapon(int weaponId)
6908 weapons[weaponId].owner = id;
6909 if (num_weapons > 0) {
6910 weaponids[num_weapons] = weaponids[0];
6913 weaponids[0] = weaponId;
6916 void Person::addClothes()
6918 if (numclothes > 0) {
6919 for (int i = 0; i < numclothes; i++) {
6926 bool Person::addClothes(const int& clothesId)
6929 const std::string fileName = clothes[clothesId];
6931 GLubyte* array = &skeleton.skinText[0];
6935 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6940 float tintr = clothestintr[clothesId];
6941 float tintg = clothestintg[clothesId];
6942 float tintb = clothestintb[clothesId];
6944 if (tintr > 1) tintr = 1;
6945 if (tintg > 1) tintg = 1;
6946 if (tintb > 1) tintb = 1;
6948 if (tintr < 0) tintr = 0;
6949 if (tintg < 0) tintg = 0;
6950 if (tintb < 0) tintb = 0;
6952 int bytesPerPixel = texture.bpp / 8;
6956 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6957 if (bytesPerPixel == 3)
6959 else if ((i + 1) % 4 == 0)
6960 alphanum = texture.data[i];
6961 if ((i + 1) % 4 || bytesPerPixel == 3) {
6963 texture.data[i] *= tintr;
6965 texture.data[i] *= tintg;
6967 texture.data[i] *= tintb;
6968 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6980 if (aitype != playercontrolled && !Dialog::inDialog()) {
6982 //disable movement in editor
6983 if (Game::editorenabled)
6987 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
6988 Person::players[0]->coords.y > coords.y + 2 &&
6989 !Person::players[0]->onterrain)
6993 if (aitype == pathfindtype) {
6994 if (finalpathfindpoint == -1) {
6995 float closestdistance;
7000 closestdistance = -1;
7001 for (int j = 0; j < Game::numpathpoints; j++) {
7002 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7003 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7005 finaltarget = Game::pathpoint[j];
7008 finalpathfindpoint = closest;
7009 for (int j = 0; j < Game::numpathpoints; j++) {
7010 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7011 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7012 if (sq(tempdist) < closestdistance)
7013 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7014 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7015 closestdistance = sq(tempdist);
7017 finaltarget = colpoint;
7021 finalpathfindpoint = closest;
7024 if (targetpathfindpoint == -1) {
7025 float closestdistance;
7030 closestdistance = -1;
7031 if (lastpathfindpoint == -1) {
7032 for (int j = 0; j < Game::numpathpoints; j++) {
7033 if (j != lastpathfindpoint)
7034 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7035 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7039 targetpathfindpoint = closest;
7040 for (int j = 0; j < Game::numpathpoints; j++)
7041 if (j != lastpathfindpoint)
7042 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7043 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint );
7044 if (sq(tempdist) < closestdistance) {
7045 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7046 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7047 closestdistance = sq(tempdist);
7052 targetpathfindpoint = closest;
7054 for (int j = 0; j < Game::numpathpoints; j++)
7055 if (j != lastpathfindpoint &&
7056 j != lastpathfindpoint2 &&
7057 j != lastpathfindpoint3 &&
7058 j != lastpathfindpoint4) {
7060 if (Game::numpathpointconnect[j])
7061 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7062 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7065 if (Game::numpathpointconnect[lastpathfindpoint])
7066 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7067 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7070 tempdist = findPathDist(j, finalpathfindpoint);
7071 if (closest == -1 || tempdist < closestdistance) {
7072 closestdistance = tempdist;
7077 targetpathfindpoint = closest;
7080 losupdatedelay -= multiplier;
7082 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7083 lookyaw = targetyaw;
7085 //reached target point
7086 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7087 lastpathfindpoint4 = lastpathfindpoint3;
7088 lastpathfindpoint3 = lastpathfindpoint2;
7089 lastpathfindpoint2 = lastpathfindpoint;
7090 lastpathfindpoint = targetpathfindpoint;
7091 if (lastpathfindpoint2 == -1)
7092 lastpathfindpoint2 = lastpathfindpoint;
7093 if (lastpathfindpoint3 == -1)
7094 lastpathfindpoint3 = lastpathfindpoint2;
7095 if (lastpathfindpoint4 == -1)
7096 lastpathfindpoint4 = lastpathfindpoint3;
7097 targetpathfindpoint = -1;
7099 if ( distsqflat(&coords, &finalfinaltarget) <
7100 distsqflat(&coords, &finaltarget) ||
7101 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7102 lastpathfindpoint == finalpathfindpoint) {
7103 aitype = passivetype;
7114 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7115 targetyaw += 90 * (whichdirection * 2 - 1);
7117 if (collided < 1 || animTarget != jumpupanim)
7119 if ((collided > .8 && jumppower >= 5))
7122 if ((!Tutorial::active || cananger) &&
7124 !Person::players[0]->dead &&
7125 distsq(&coords, &Person::players[0]->coords) < 400 &&
7127 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7128 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7129 !Game::editorenabled &&
7130 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7131 aitype = attacktypecutoff;
7132 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7133 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7134 !Game::editorenabled)
7135 aitype = attacktypecutoff;
7137 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7138 losupdatedelay = .2;
7139 for (unsigned j = 0; j < Person::players.size(); j++)
7140 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7141 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7142 if (distsq(&coords, &Person::players[j]->coords) < 400)
7143 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7144 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7145 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
7146 DoRotation(jointPos(head), 0, yaw, 0)
7148 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
7149 *Person::players[j]->scale + Person::players[j]->coords) ||
7150 (Person::players[j]->animTarget == hanganim &&
7151 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7152 aitype = searchtype;
7154 lastseen = Person::players[j]->coords;
7159 if (aitype == attacktypecutoff && Game::musictype != 2)
7160 if (creature != wolftype) {
7166 if (aitype != passivetype && Game::leveltime > .5)
7167 howactive = typeactive;
7169 if (aitype == passivetype) {
7170 aiupdatedelay -= multiplier;
7171 losupdatedelay -= multiplier;
7172 lastseentime += multiplier;
7173 pausetime -= multiplier;
7174 if (lastseentime > 1)
7177 if (aiupdatedelay < 0) {
7178 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7179 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7180 lookyaw = targetyaw;
7181 aiupdatedelay = .05;
7183 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7184 if (waypointtype[waypoint] == wppause)
7187 if (waypoint > numwaypoints - 1)
7193 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7204 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7205 if (!avoidsomething)
7206 targetyaw += 90 * (whichdirection * 2 - 1);
7208 XYZ leftpos, rightpos;
7209 float leftdist, rightdist;
7210 leftpos = coords + DoRotation(facing, 0, 90, 0);
7211 rightpos = coords - DoRotation(facing, 0, 90, 0);
7212 leftdist = distsq(&leftpos, &avoidwhere);
7213 rightdist = distsq(&rightpos, &avoidwhere);
7214 if (leftdist < rightdist)
7221 if (collided < 1 || animTarget != jumpupanim)
7223 if ((collided > .8 && jumppower >= 5))
7228 if (!Game::editorenabled) {
7229 if (howactive <= typesleeping)
7230 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7231 for (int j = 0; j < numenvsounds; j++) {
7232 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7233 if (vol > 0 && distsq(&coords, &envsound[j]) <
7234 2 * (vol + vol * (creature == rabbittype) * 3))
7235 aitype = attacktypecutoff;
7238 if (aitype != passivetype) {
7239 if (howactive == typesleeping)
7240 setTargetAnimation(getupfromfrontanim);
7241 howactive = typeactive;
7245 if (howactive < typesleeping &&
7246 ((!Tutorial::active || cananger) && hostile) &&
7247 !Person::players[0]->dead &&
7248 distsq(&coords, &Person::players[0]->coords) < 400 &&
7250 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7251 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7252 aitype = attacktypecutoff;
7253 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7254 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7255 aitype = attacktypecutoff;
7258 if (creature == wolftype) {
7260 for (unsigned j = 0; j < Person::players.size(); j++) {
7261 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7262 float smelldistance = 50;
7263 if (j == 0 && Person::players[j]->num_weapons > 0) {
7264 if (weapons[Person::players[j]->weaponids[0]].bloody)
7265 smelldistance = 100;
7266 if (Person::players[j]->num_weapons == 2)
7267 if (weapons[Person::players[j]->weaponids[1]].bloody)
7268 smelldistance = 100;
7271 smelldistance = 100;
7272 windsmell = windvector;
7273 Normalise(&windsmell);
7274 windsmell = windsmell * 2 + Person::players[j]->coords;
7275 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7276 aitype = attacktypecutoff;
7281 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7282 losupdatedelay = .2;
7283 for (unsigned j = 0; j < Person::players.size(); j++) {
7284 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7285 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7286 if (distsq(&coords, &Person::players[j]->coords) < 400)
7287 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7288 if ((-1 == Object::checkcollide(
7289 DoRotation(jointPos(head), 0, yaw, 0)*
7291 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
7292 Person::players[j]->scale + Person::players[j]->coords) &&
7293 !Person::players[j]->isWallJump()) ||
7294 (Person::players[j]->animTarget == hanganim &&
7295 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7297 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7302 if (lastseentime <= 0) {
7303 aitype = searchtype;
7305 lastseen = Person::players[j]->coords;
7313 if (aitype == attacktypecutoff && Game::musictype != 2) {
7314 if (creature != wolftype) {
7318 if (creature == wolftype) {
7328 if (aitype == searchtype) {
7329 aiupdatedelay -= multiplier;
7330 losupdatedelay -= multiplier;
7332 lastseentime -= multiplier;
7333 lastchecktime -= multiplier;
7335 if (isRun() && !onground) {
7336 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7337 XYZ test2 = coords + facing;
7339 XYZ test = coords + facing;
7341 j = Object::checkcollide(test2, test, laststanding);
7343 j = Object::checkcollide(test2, test);
7346 setTargetAnimation(getStop());
7349 //aitype=passivetype;
7350 aitype = pathfindtype;
7351 finalfinaltarget = waypoints[waypoint];
7352 finalpathfindpoint = -1;
7353 targetpathfindpoint = -1;
7354 lastpathfindpoint = -1;
7355 lastpathfindpoint2 = -1;
7356 lastpathfindpoint3 = -1;
7357 lastpathfindpoint4 = -1;
7362 //check out last seen location
7363 if (aiupdatedelay < 0) {
7364 targetyaw = roughDirectionTo(coords, lastseen);
7365 lookyaw = targetyaw;
7366 aiupdatedelay = .05;
7369 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7372 lastseen.x += (float(Random() % 100) - 50) / 25;
7373 lastseen.z += (float(Random() % 100) - 50) / 25;
7384 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7385 if (!avoidsomething)
7386 targetyaw += 90 * (whichdirection * 2 - 1);
7388 XYZ leftpos, rightpos;
7389 float leftdist, rightdist;
7390 leftpos = coords + DoRotation(facing, 0, 90, 0);
7391 rightpos = coords - DoRotation(facing, 0, 90, 0);
7392 leftdist = distsq(&leftpos, &avoidwhere);
7393 rightdist = distsq(&rightpos, &avoidwhere);
7394 if (leftdist < rightdist)
7401 if (collided < 1 || animTarget != jumpupanim)
7403 if ((collided > .8 && jumppower >= 5))
7406 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7407 for (int k = 0; k < numenvsounds; k++) {
7408 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7409 aitype = attacktypecutoff;
7413 if (!Person::players[0]->dead &&
7414 losupdatedelay < 0 &&
7415 !Game::editorenabled &&
7417 ((!Tutorial::active || cananger) && hostile)) {
7418 losupdatedelay = .2;
7419 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7420 aitype = attacktypecutoff;
7423 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7424 //TODO: factor out canSeePlayer()
7425 if (distsq(&coords, &Person::players[0]->coords) < 400)
7426 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7427 if ((Object::checkcollide(
7428 DoRotation(jointPos(head), 0, yaw, 0)*
7430 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
7431 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
7432 (Person::players[0]->animTarget == hanganim && normaldotproduct(
7433 Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7434 /* //TODO: changed j to 0 on a whim, make sure this is correct
7435 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7436 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7438 aitype = attacktypecutoff;
7443 if (lastseentime < 0) {
7444 //aitype=passivetype;
7446 aitype = pathfindtype;
7447 finalfinaltarget = waypoints[waypoint];
7448 finalpathfindpoint = -1;
7449 targetpathfindpoint = -1;
7450 lastpathfindpoint = -1;
7451 lastpathfindpoint2 = -1;
7452 lastpathfindpoint3 = -1;
7453 lastpathfindpoint4 = -1;
7457 if (aitype != gethelptype)
7460 //get help from buddies
7461 if (aitype == gethelptype) {
7462 runninghowlong += multiplier;
7463 aiupdatedelay -= multiplier;
7465 if (aiupdatedelay < 0 || ally == 0) {
7469 //TODO: factor out closest search somehow
7472 float closestdist = -1;
7473 for (unsigned k = 0; k < Person::players.size(); k++) {
7474 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7475 (Person::players[k]->howactive < typedead1) &&
7476 !Person::players[k]->skeleton.free &&
7477 (Person::players[k]->aitype == passivetype)) {
7478 float distance = distsq(&coords, &Person::players[k]->coords);
7479 if (closestdist == -1 || distance < closestdist) {
7480 closestdist = distance;
7486 if (closest != -1) {
7491 lastseen = Person::players[0]->coords;
7498 XYZ facing = coords;
7499 XYZ flatfacing = Person::players[ally]->coords;
7500 facing.y += jointPos(head).y * scale;
7501 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7502 if (-1 != Object::checkcollide(facing, flatfacing))
7505 //no available ally, run back to player
7507 Person::players[ally]->skeleton.free ||
7508 Person::players[ally]->aitype != passivetype ||
7509 lastseentime <= 0) {
7510 aitype = searchtype;
7516 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7517 lookyaw = targetyaw;
7518 aiupdatedelay = .05;
7521 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7522 aitype = searchtype;
7524 Person::players[ally]->aitype = searchtype;
7525 if (Person::players[ally]->lastseentime < lastseentime) {
7526 Person::players[ally]->lastseen = lastseen;
7527 Person::players[ally]->lastseentime = lastseentime;
7528 Person::players[ally]->lastchecktime = lastchecktime;
7532 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7533 if (!avoidsomething)
7534 targetyaw += 90 * (whichdirection * 2 - 1);
7536 XYZ leftpos, rightpos;
7537 float leftdist, rightdist;
7538 leftpos = coords + DoRotation(facing, 0, 90, 0);
7539 rightpos = coords - DoRotation(facing, 0, 90, 0);
7540 leftdist = distsq(&leftpos, &avoidwhere);
7541 rightdist = distsq(&rightpos, &avoidwhere);
7542 if (leftdist < rightdist)
7556 if (collided < 1 || animTarget != jumpupanim)
7558 if (collided > .8 && jumppower >= 5)
7562 //retreiving a weapon on the ground
7563 if (aitype == getweapontype) {
7564 aiupdatedelay -= multiplier;
7565 lastchecktime -= multiplier;
7567 if (aiupdatedelay < 0) {
7573 float closestdist = -1;
7574 for (unsigned k = 0; k < weapons.size(); k++)
7575 if (weapons[k].owner == -1) {
7576 float distance = distsq(&coords, &weapons[k].position);
7577 if (closestdist == -1 || distance < closestdist) {
7578 closestdist = distance;
7591 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7592 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7593 aitype = attacktypecutoff;
7596 if (!Person::players[0]->dead)
7598 if (weapons[ally].owner != -1 ||
7599 distsq(&coords, &weapons[ally].position) > 16) {
7600 aitype = attacktypecutoff;
7603 //TODO: factor these out as moveToward()
7604 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7605 lookyaw = targetyaw;
7606 aiupdatedelay = .05;
7610 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7611 if (!avoidsomething)
7612 targetyaw += 90 * (whichdirection * 2 - 1);
7614 XYZ leftpos, rightpos;
7615 float leftdist, rightdist;
7616 leftpos = coords + DoRotation(facing, 0, 90, 0);
7617 rightpos = coords - DoRotation(facing, 0, 90, 0);
7618 leftdist = distsq(&leftpos, &avoidwhere);
7619 rightdist = distsq(&rightpos, &avoidwhere);
7620 if (leftdist < rightdist)
7634 if (animTarget != crouchremoveknifeanim &&
7635 animTarget != removeknifeanim)
7636 throwtogglekeydown = 0;
7639 if (collided < 1 || animTarget != jumpupanim)
7641 if ((collided > .8 && jumppower >= 5))
7645 if (aitype == attacktypecutoff) {
7646 aiupdatedelay -= multiplier;
7647 //dodge or reverse rabbit kicks, knife throws, flips
7648 if (damage < damagetolerance * 2 / 3)
7649 if ((Person::players[0]->animTarget == rabbitkickanim ||
7650 Person::players[0]->animTarget == knifethrowanim ||
7651 (Person::players[0]->isFlip() &&
7652 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7653 !Person::players[0]->skeleton.free &&
7654 (aiupdatedelay < .1)) {
7658 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7659 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7660 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7661 if (abs(Random() % 2) == 0) {
7662 setTargetAnimation(backhandspringanim);
7664 setTargetAnimation(rollanim);
7666 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7669 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
7670 setTargetAnimation(flipanim);
7675 aiupdatedelay = .02;
7677 //get confused by flips
7678 if (Person::players[0]->isFlip() &&
7679 !Person::players[0]->skeleton.free &&
7680 Person::players[0]->animTarget != walljumprightkickanim &&
7681 Person::players[0]->animTarget != walljumpleftkickanim) {
7682 if (distsq(&Person::players[0]->coords, &coords) < 25)
7683 if ((1 - damage / damagetolerance) > .5)
7686 //go for weapon on the ground
7687 if (wentforweapon < 3)
7688 for (unsigned k = 0; k < weapons.size(); k++)
7689 if (creature != wolftype)
7690 if (num_weapons == 0 &&
7691 weapons[k].owner == -1 &&
7692 weapons[k].velocity.x == 0 &&
7693 weapons[k].velocity.z == 0 &&
7694 weapons[k].velocity.y == 0) {
7695 if (distsq(&coords, &weapons[k].position) < 16) {
7698 aitype = getweapontype;
7702 //dodge/reverse walljump kicks
7703 if (damage < damagetolerance / 2)
7704 if (Animation::animations[animTarget].height != highheight)
7705 if (damage < damagetolerance * .5 &&
7706 ((Person::players[0]->animTarget == walljumprightkickanim ||
7707 Person::players[0]->animTarget == walljumpleftkickanim) &&
7708 ((aiupdatedelay < .15 &&
7710 (aiupdatedelay < .08 &&
7711 difficulty != 2)))) {
7714 //walked off a ledge (?)
7715 if (isRun() && !onground)
7716 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7717 XYZ test2 = coords + facing;
7719 XYZ test = coords + facing;
7721 j = Object::checkcollide(test2, test, laststanding);
7723 j = Object::checkcollide(test2, test);
7726 setTargetAnimation(getStop());
7729 aitype = pathfindtype;
7730 finalfinaltarget = waypoints[waypoint];
7731 finalpathfindpoint = -1;
7732 targetpathfindpoint = -1;
7733 lastpathfindpoint = -1;
7734 lastpathfindpoint2 = -1;
7735 lastpathfindpoint3 = -1;
7736 lastpathfindpoint4 = -1;
7740 //lose sight of player in the air (?)
7741 if (Person::players[0]->coords.y > coords.y + 5 &&
7742 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7743 !Person::players[0]->onterrain) {
7744 aitype = pathfindtype;
7745 finalfinaltarget = waypoints[waypoint];
7746 finalpathfindpoint = -1;
7747 targetpathfindpoint = -1;
7748 lastpathfindpoint = -1;
7749 lastpathfindpoint2 = -1;
7750 lastpathfindpoint3 = -1;
7751 lastpathfindpoint4 = -1;
7753 //it's time to think (?)
7754 if (aiupdatedelay < 0 &&
7755 !Animation::animations[animTarget].attack &&
7756 animTarget != staggerbackhighanim &&
7757 animTarget != staggerbackhardanim &&
7758 animTarget != backhandspringanim &&
7759 animTarget != dodgebackanim) {
7761 if (weaponactive == -1 && num_weapons > 0)
7762 drawkeydown = Random() % 2;
7765 rabbitkickenabled = Random() % 2;
7767 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7768 XYZ targetpoint = Person::players[0]->coords;
7769 if (distsq(&Person::players[0]->coords, &coords) <
7770 distsq(&rotatetarget, &coords))
7771 targetpoint += Person::players[0]->velocity *
7772 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7773 targetyaw = roughDirectionTo(coords, targetpoint);
7774 lookyaw = targetyaw;
7775 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7777 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7779 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7780 distsq(&coords, &Person::players[0]->coords) < 9) &&
7781 Person::players[0]->weaponactive != -1)
7783 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7787 //chill out around the corpse
7788 if (Person::players[0]->dead) {
7790 if (Random() % 10 == 0)
7792 if (Random() % 100 == 0) {
7793 aitype = pathfindtype;
7794 finalfinaltarget = waypoints[waypoint];
7795 finalpathfindpoint = -1;
7796 targetpathfindpoint = -1;
7797 lastpathfindpoint = -1;
7798 lastpathfindpoint2 = -1;
7799 lastpathfindpoint3 = -1;
7800 lastpathfindpoint4 = -1;
7809 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7810 targetyaw += 90 * (whichdirection * 2 - 1);
7812 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7816 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7820 if (aitype != playercontrolled &&
7825 for (unsigned j = 0; j < Person::players.size(); j++)
7826 if (j != id && !Person::players[j]->skeleton.free &&
7827 Person::players[j]->hasvictim &&
7828 (Tutorial::active && reversaltrain ||
7829 Random() % 2 == 0 && difficulty == 2 ||
7830 Random() % 4 == 0 && difficulty == 1 ||
7831 Random() % 8 == 0 && difficulty == 0 ||
7832 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7833 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7834 (Random() % 2 == 0 || difficulty == 2) ||
7835 (isIdle() || isRun()) &&
7836 Person::players[j]->weaponactive != -1 ||
7837 Person::players[j]->animTarget == swordslashanim &&
7838 weaponactive != -1 ||
7839 Person::players[j]->animTarget == staffhitanim ||
7840 Person::players[j]->animTarget == staffspinhitanim))
7841 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7842 Person::players[j]->victim == Person::players[id] &&
7843 (Person::players[j]->animTarget == sweepanim ||
7844 Person::players[j]->animTarget == spinkickanim ||
7845 Person::players[j]->animTarget == staffhitanim ||
7846 Person::players[j]->animTarget == staffspinhitanim ||
7847 Person::players[j]->animTarget == winduppunchanim ||
7848 Person::players[j]->animTarget == upunchanim ||
7849 Person::players[j]->animTarget == wolfslapanim ||
7850 Person::players[j]->animTarget == knifeslashstartanim ||
7851 Person::players[j]->animTarget == swordslashanim &&
7852 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7853 weaponactive != -1))) {
7861 Person::players[target]->Reverse();
7866 if (collided > .8 && jumppower >= 5 ||
7867 distsq(&coords, &Person::players[0]->coords) > 400 &&
7869 creature == rabbittype)
7871 //TODO: why are we controlling the human?
7872 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7873 Person::players[0]->jumpkeydown = 0;
7874 if (Person::players[0]->animTarget == jumpdownanim &&
7875 distsq(&Person::players[0]->coords, &coords) < 40)
7880 if (Tutorial::active)
7885 XYZ facing = coords;
7886 XYZ flatfacing = Person::players[0]->coords;
7887 facing.y += jointPos(head).y * scale;
7888 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7890 if (-1 != Object::checkcollide(facing, flatfacing)) {
7893 if (lastseentime <= 0 &&
7894 (creature != wolftype ||
7895 weaponstuck == -1)) {
7896 aitype = searchtype;
7898 lastseen = Person::players[0]->coords;
7905 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7906 (aitype == attacktypecutoff ||
7907 aitype == searchtype))
7908 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7909 XYZ test = Person::players[0]->coords;
7911 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7915 if (aitype == passivetype && !(numwaypoints > 1) ||
7917 pause && damage > superpermanentdamage) {
7936 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7937 facing = flatfacing;
7939 if (aitype == attacktypecutoff) {
7940 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7941 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7942 } else if (howactive >= typesleeping) {
7943 targetheadyaw = targetyaw;
7944 targetheadpitch = 0;
7946 if (interestdelay <= 0) {
7947 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
7948 headtarget = coords;
7949 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
7950 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
7951 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
7952 headtarget += facing * 1.5;
7954 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
7955 targetheadpitch = pitchTo(coords, headtarget);