2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/openal_wrapper.hpp"
25 #include "Audio/Sounds.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Utils/Folders.hpp"
30 #include "Tutorial.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
54 extern bool decalstoggle;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern float smoketex;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern bool gamestarted;
70 extern XYZ envsound[30];
71 extern float envsoundvol[30];
72 extern int numenvsounds;
73 extern float envsoundlife[30];
75 extern XYZ windvector;
77 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
82 animCurrent(bounceidleanim),
83 animTarget(bounceidleanim),
90 howactive(typeactive),
92 superruntoggle(false),
93 lastattack(0), lastattack2(0), lastattack3(0),
94 currentoffset(), targetoffset(), offset(),
126 rabbitkickenabled(false),
135 damagetolerance(200),
138 superpermanentdamage(0),
152 bleedx(0), bleedy(0),
156 headyaw(0), headpitch(0),
157 targetheadyaw(0), targetheadpitch(0),
168 normalsupdatedelay(0),
171 forwardkeydown(false),
172 forwardstogglekeydown(false),
177 jumptogglekeydown(false),
178 crouchkeydown(false),
179 crouchtogglekeydown(false),
181 drawtogglekeydown(false),
183 throwtogglekeydown(false),
184 attackkeydown(false),
189 crouchkeydowntime(0),
203 whichdirection(false),
204 whichdirectiondelay(0),
205 avoidsomething(false),
214 lefthandmorphness(0),
215 righthandmorphness(0),
219 targetlefthandmorphness(0),
220 targetrighthandmorphness(0),
221 targetheadmorphness(1),
222 targetchestmorphness(0),
223 targettailmorphness(0),
224 lefthandmorphstart(0), lefthandmorphend(0),
225 righthandmorphstart(0), righthandmorphend(0),
226 headmorphstart(0), headmorphend(0),
227 chestmorphstart(0), chestmorphend(0),
228 tailmorphstart(0), tailmorphend(0),
231 highreversaldelay(0),
234 creature(rabbittype),
281 finalpathfindpoint(0),
282 targetpathfindpoint(0),
283 lastpathfindpoint(0),
284 lastpathfindpoint2(0),
285 lastpathfindpoint3(0),
286 lastpathfindpoint4(0),
303 neckspurtparticledelay(0),
307 rabbitkickragdoll(false),
315 /* Read a person in tfile. Throws an error if it’s not valid */
316 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
319 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
321 funpackf(tfile, "Bi", &howactive);
323 howactive = typeactive;
326 funpackf(tfile, "Bf", &scale);
331 funpackf(tfile, "Bb", &immobile);
336 funpackf(tfile, "Bf", &yaw);
341 if (num_weapons < 0 || num_weapons > 5) {
342 throw InvalidPersonException();
344 if (num_weapons > 0 && num_weapons < 5) {
345 for (int j = 0; j < num_weapons; j++) {
346 weaponids[j] = weapons.size();
348 funpackf(tfile, "Bi", &type);
349 weapons.push_back(Weapon(type, id));
352 funpackf(tfile, "Bi", &numwaypoints);
353 for (int j = 0; j < numwaypoints; j++) {
354 funpackf(tfile, "Bf", &waypoints[j].x);
355 funpackf(tfile, "Bf", &waypoints[j].y);
356 funpackf(tfile, "Bf", &waypoints[j].z);
358 funpackf(tfile, "Bi", &waypointtype[j]);
360 waypointtype[j] = wpkeepwalking;
364 funpackf(tfile, "Bi", &waypoint);
365 if (waypoint > (numwaypoints - 1)) {
369 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
370 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
371 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
372 funpackf(tfile, "Bf Bf", &power, &speedmult);
374 float headprop, legprop, armprop, bodyprop;
377 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
385 if (creature == wolftype) {
386 proportionhead = 1.1 * headprop;
387 proportionbody = 1.1 * bodyprop;
388 proportionarms = 1.1 * armprop;
389 proportionlegs = 1.1 * legprop;
390 } else if (creature == rabbittype) {
391 proportionhead = 1.2 * headprop;
392 proportionbody = 1.05 * bodyprop;
393 proportionarms = 1.00 * armprop;
394 proportionlegs = 1.1 * legprop;
395 proportionlegs.y = 1.05 * legprop;
398 funpackf(tfile, "Bi", &numclothes);
399 for (int k = 0; k < numclothes; k++) {
401 funpackf(tfile, "Bi", &templength);
402 for (int l = 0; l < templength; l++)
403 funpackf(tfile, "Bb", &clothes[k][l]);
404 clothes[k][templength] = '\0';
405 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
411 if (creature == wolftype) {
413 damagetolerance = 300;
420 realoldcoords = coords;
423 void Person::skeletonLoad(bool clothes)
426 if (creature != wolftype) {
428 "Skeleton/BasicFigure",
429 "Skeleton/BasicFigureLow",
430 "Skeleton/RabbitBelt",
432 "Models/Body2.solid",
433 "Models/Body3.solid",
434 "Models/Body4.solid",
435 "Models/Body5.solid",
436 "Models/Body6.solid",
437 "Models/Body7.solid",
438 "Models/BodyLow.solid",
444 "Skeleton/BasicFigureWolf",
445 "Skeleton/BasicFigureWolfLow",
446 "Skeleton/RabbitBelt",
448 "Models/Wolf2.solid",
449 "Models/Wolf3.solid",
450 "Models/Wolf4.solid",
451 "Models/Wolf5.solid",
452 "Models/Wolf6.solid",
453 "Models/Wolf7.solid",
454 "Models/WolfLow.solid",
460 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
466 * GameTick/doPlayerCollisions
468 void Person::CheckKick()
471 && (animTarget == rabbitkickanim
473 && victim != this->shared_from_this()
475 && animCurrent == rabbitkickanim)
476 && distsq(&coords, &victim->coords) < 1.2
477 && !victim->skeleton.free))
480 if (Animation::animations[victim->animTarget].height != lowheight) {
481 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
482 XYZ relative = velocity;
484 Normalise(&relative);
488 if (!Tutorial::active)
489 emit_sound_at(heavyimpactsound, victim->coords);
491 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
492 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
495 victim->DoDamage(100 * damagemult / victim->protectionhigh);
501 animTarget = backflipanim;
503 velocity = facing * -10;
507 resume_stream(whooshsound);
509 award_bonus(id, cannon);
510 } else if (victim->isCrouch()) {
511 animTarget = rabbitkickreversedanim;
512 animCurrent = rabbitkickreversedanim;
513 victim->animCurrent = rabbitkickreversalanim;
514 victim->animTarget = rabbitkickreversalanim;
520 victim->oldcoords = victim->coords;
521 coords = victim->coords;
522 victim->targetyaw = targetyaw;
523 victim->victim = this->shared_from_this();
530 * GameTick/doPlayerCollisions - spread fire between players
531 * GameTick/doDevKeys - press f to ignite
532 * Person::DoStuff - spread fire from lit campfires and bushes
534 void Person::CatchFire()
536 XYZ flatfacing, flatvelocity;
538 for (int i = 0; i < 10; i++) {
539 howmany = fabs(Random() % (skeleton.joints.size()));
541 flatvelocity = skeleton.joints[howmany].velocity;
542 flatfacing = skeleton.joints[howmany].position * scale + coords;
544 flatvelocity = velocity;
545 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
547 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
552 emit_sound_at(firestartsound, coords);
554 emit_stream_at(stream_firesound, coords);
562 * idle animation for this creature (depending on status)
564 int Person::getIdle()
566 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
568 if (hasvictim && (victim != this->shared_from_this())) {
569 if ((!victim->dead && victim->aitype != passivetype &&
570 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
571 victim->id < Person::players.size())) {
572 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
573 if (creature == rabbittype)
574 return fightidleanim;
575 if (creature == wolftype)
578 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
579 if (weapons[weaponids[weaponactive]].getType() == knife)
580 return knifefightidleanim;
581 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
582 return swordfightidlebothanim;
583 if (weapons[weaponids[weaponactive]].getType() == sword)
584 return swordfightidleanim;
585 if (weapons[weaponids[weaponactive]].getType() == staff)
586 return swordfightidleanim;
588 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
589 return fightsidestep;
592 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
594 if (howactive == typesitting) return sitanim;
595 if (howactive == typesittingwall) return sitwallanim;
596 if (howactive == typesleeping) return sleepanim;
597 if (howactive == typedead1) return dead1anim;
598 if (howactive == typedead2) return dead2anim;
599 if (howactive == typedead3) return dead3anim;
600 if (howactive == typedead4) return dead4anim;
601 if (creature == rabbittype) return bounceidleanim;
602 if (creature == wolftype) return wolfidle;
607 * crouch animation for this creature
609 int Person::getCrouch()
611 if (creature == rabbittype)
613 if (creature == wolftype)
614 return wolfcrouchanim;
619 * running animation for this creature (can be upright or all fours)
623 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
625 if (creature == wolftype && (!superruntoggle))
628 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
629 return rabbitrunninganim;
630 if (creature == wolftype && (superruntoggle))
631 return wolfrunninganim;
637 int Person::getStop()
639 if (creature == rabbittype)
641 if (creature == wolftype)
648 int Person::getLanding()
650 if (creature == rabbittype)
652 if (creature == wolftype)
659 int Person::getLandhard()
661 if (creature == rabbittype)
663 if (creature == wolftype)
664 return wolflandhardanim;
671 * Person::DoAnimations
674 SolidHitBonus(int playerid)
676 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
677 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
679 award_bonus(playerid, solidhit);
683 * spawns blood effects
685 void Person::DoBlood(float howmuch, int which)
687 // FIXME: should abstract out inputs
688 static int bleedxint, bleedyint;
690 if (bloodtoggle && !Tutorial::active) {
691 if (bleeding <= 0 && spurt) {
693 for (int i = 0; i < 3; i++) {
694 // emit blood particles
697 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
698 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
699 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
700 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
703 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
704 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
705 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
706 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
709 if (Random() % 2 == 0) // 50% chance
710 for (int i = 0; i < 3; i++) {
711 if (Random() % 2 != 0) {
712 // emit teeth particles
715 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
716 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
719 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
720 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
724 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
726 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
728 Sprite::setLastSpriteSpecial(3); // sets it to teeth
733 // FIXME: manipulating attributes
734 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
737 if (creature == rabbittype)
738 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
739 bleedxint = abs(Random() % 512);
740 bleedyint = abs(Random() % 512);
742 if (creature == wolftype)
743 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
744 bleedxint = abs(Random() % 512);
745 bleedyint = abs(Random() % 512);
749 bleedy /= realtexdetail;
750 bleedx /= realtexdetail;
751 direction = abs(Random() % 2) * 2 - 1;
760 * spawns big blood effects and ???
761 * modifies character's skin texture
763 void Person::DoBloodBig(float howmuch, int which)
765 static int bleedxint, bleedyint, i, j;
767 if (howmuch && id == 0)
770 if (!Tutorial::active || id == 0)
771 if (aitype != playercontrolled && howmuch > 0) {
775 if (creature == wolftype) {
776 int i = abs(Random() % 2);
778 whichsound = snarlsound;
780 whichsound = snarl2sound;
782 if (creature == rabbittype) {
783 int i = abs(Random() % 2);
785 whichsound = rabbitpainsound;
786 if (i == 1 && howmuch >= 2)
787 whichsound = rabbitpain1sound;
790 if (whichsound != -1) {
791 emit_sound_at(whichsound, coords);
796 if (id == 0 && howmuch > 0) {
800 if (bloodtoggle && decalstoggle && !Tutorial::active) {
801 if (bleeding <= 0 && spurt) {
803 for (int i = 0; i < 3; i++) {
804 // emit blood particles
805 // FIXME: copypaste from above
808 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
809 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
810 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
811 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
814 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
815 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
816 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
817 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
822 // weird texture manipulation code follows.
823 // looks like this is painting blood onto the character's skin texture
824 // FIXME: surely there's a better way
826 int offsetx = 0, offsety = 0;
828 offsety = Random() % 40;
829 offsetx = abs(Random() % 60);
831 if (which == 190 || which == 185) {
832 offsety = Random() % 40;
833 offsetx = abs(Random() % 100) - 20;
836 offsety = Random() % 10;
837 offsetx = Random() % 10;
840 offsety = Random() % 20;
841 offsetx = Random() % 20;
843 if (which == 220 || which == 215) {
853 if (creature == rabbittype)
854 for (i = 0; i < 512; i++) {
855 for (j = 0; j < 512; j++) {
856 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
857 if (i < startx) startx = i;
858 if (j < starty) starty = j;
859 if (i > endx) endx = i;
860 if (j > endy) endy = j;
864 if (creature == wolftype)
865 for (i = 0; i < 512; i++) {
866 for (j = 0; j < 512; j++) {
867 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
868 if (i < startx) startx = i;
869 if (j < starty) starty = j;
870 if (i > endx) endx = i;
871 if (j > endy) endy = j;
881 if (startx < 0) startx = 0;
882 if (starty < 0) starty = 0;
883 if (endx > 512 - 1) endx = 512 - 1;
884 if (endy > 512 - 1) endy = 512 - 1;
885 if (endx < startx) endx = startx;
886 if (endy < starty) endy = starty;
888 startx /= realtexdetail;
889 starty /= realtexdetail;
890 endx /= realtexdetail;
891 endy /= realtexdetail;
893 int texdetailint = realtexdetail;
895 if (creature == rabbittype)
896 for (i = startx; i < endx; i++) {
897 for (j = starty; j < endy; j++) {
898 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
899 color = Random() % 85 + 170;
900 where = i * skeleton.skinsize * 3 + j * 3;
901 if (skeleton.skinText[where + 0] > color / 2)
902 skeleton.skinText[where + 0] = color / 2;
903 skeleton.skinText[where + 1] = 0;
904 skeleton.skinText[where + 2] = 0;
908 if (creature == wolftype)
909 for (i = startx; i < endx; i++) {
910 for (j = starty; j < endy; j++) {
911 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
912 color = Random() % 85 + 170;
913 where = i * skeleton.skinsize * 3 + j * 3;
914 if (skeleton.skinText[where + 0] > color / 2)
915 skeleton.skinText[where + 0] = color / 2;
916 skeleton.skinText[where + 1] = 0;
917 skeleton.skinText[where + 2] = 0;
921 skeleton.drawmodel.textureptr.bind();
926 if (creature == rabbittype)
927 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
928 bleedxint = abs(Random() % 512);
929 bleedyint = abs(Random() % 512);
931 if (creature == wolftype)
932 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
933 bleedxint = abs(Random() % 512);
934 bleedyint = abs(Random() % 512);
936 bleedy = bleedxint + offsetx;
937 bleedx = bleedyint + offsety;
938 bleedy /= realtexdetail;
939 bleedx /= realtexdetail;
944 if (bleedx > skeleton.skinsize - 1)
945 bleedx = skeleton.skinsize - 1;
946 if (bleedy > skeleton.skinsize - 1)
947 bleedy = skeleton.skinsize - 1;
948 direction = abs(Random() % 2) * 2 - 1;
951 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
952 deathbleeding += bleeding;
953 bloodloss += bleeding * 3;
955 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
956 if (abs(Random() % 2) == 0) {
957 aitype = gethelptype;
960 aitype = attacktypecutoff;
968 * similar to DoBloodBig
970 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
974 static XYZ startpoint, endpoint, colpoint, movepoint;
975 static float rotationpoint;
977 static XYZ p1, p2, p3, p0;
980 float coordsx, coordsy;
983 if (bloodtoggle && decalstoggle && !Tutorial::active) {
986 where = DoRotation(where, 0, -yaw, 0);
994 // ray testing for a tri in the character model
995 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
996 if (whichtri != -1) {
997 // low level geometry math
999 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
1000 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
1001 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
1003 bary.x = distsq(&p0, &p1);
1004 bary.y = distsq(&p0, &p2);
1005 bary.z = distsq(&p0, &p3);
1007 total = bary.x + bary.y + bary.z;
1012 bary.x = 1 - bary.x;
1013 bary.y = 1 - bary.y;
1014 bary.z = 1 - bary.z;
1016 total = bary.x + bary.y + bary.z;
1022 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1023 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1024 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1025 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1026 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1027 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1028 coordsx = skeleton.drawmodel.Triangles[whichtri].gx[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gx[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gx[2] * bary.z;
1029 coordsy = skeleton.drawmodel.Triangles[whichtri].gy[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gy[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gy[2] * bary.z;
1031 if (bleeding <= 0 && spurt) {
1033 for (int i = 0; i < 3; i++) {
1034 // emit blood particles
1035 // FIXME: more copypaste code
1037 if (skeleton.free) {
1038 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1039 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1040 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1041 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1044 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1045 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1046 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1047 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1052 // texture manipulation follows
1054 int offsetx = 0, offsety = 0;
1055 offsetx = (1 + coordsy) * 512 - 291;
1056 offsety = coordsx * 512 - 437;
1063 if (creature == rabbittype)
1064 for (i = 0; i < 512; i++) {
1065 for (j = 0; j < 512; j++) {
1066 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1067 if (i < startx) startx = i;
1068 if (j < starty) starty = j;
1069 if (i > endx) endx = i;
1070 if (j > endy) endy = j;
1074 if (creature == wolftype)
1075 for (i = 0; i < 512; i++) {
1076 for (j = 0; j < 512; j++) {
1077 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1078 if (i < startx) startx = i;
1079 if (j < starty) starty = j;
1080 if (i > endx) endx = i;
1081 if (j > endy) endy = j;
1090 if (startx < 0) startx = 0;
1091 if (starty < 0) starty = 0;
1092 if (endx > 512 - 1) endx = 512 - 1;
1093 if (endy > 512 - 1) endy = 512 - 1;
1094 if (endx < startx) endx = startx;
1095 if (endy < starty) endy = starty;
1097 startx /= realtexdetail;
1098 starty /= realtexdetail;
1099 endx /= realtexdetail;
1100 endy /= realtexdetail;
1102 int texdetailint = realtexdetail;
1104 if (creature == rabbittype)
1105 for (i = startx; i < endx; i++) {
1106 for (j = starty; j < endy; j++) {
1107 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1108 color = Random() % 85 + 170;
1109 where = i * skeleton.skinsize * 3 + j * 3;
1110 if (skeleton.skinText[where + 0] > color / 2)
1111 skeleton.skinText[where + 0] = color / 2;
1112 skeleton.skinText[where + 1] = 0;
1113 skeleton.skinText[where + 2] = 0;
1114 } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1115 color = Random() % 85 + 170;
1116 where = i * skeleton.skinsize * 3 + j * 3;
1117 if (skeleton.skinText[where + 0] > color / 2)
1118 skeleton.skinText[where + 0] = color / 2;
1119 skeleton.skinText[where + 1] = 0;
1120 skeleton.skinText[where + 2] = 0;
1124 if (creature == wolftype)
1125 for (i = startx; i < endx; i++) {
1126 for (j = starty; j < endy; j++) {
1127 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1128 color = Random() % 85 + 170;
1129 where = i * skeleton.skinsize * 3 + j * 3;
1130 if (skeleton.skinText[where + 0] > color / 2)
1131 skeleton.skinText[where + 0] = color / 2;
1132 skeleton.skinText[where + 1] = 0;
1133 skeleton.skinText[where + 2] = 0;
1134 } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1135 color = Random() % 85 + 170;
1136 where = i * skeleton.skinsize * 3 + j * 3;
1137 if (skeleton.skinText[where + 0] > color / 2)
1138 skeleton.skinText[where + 0] = color / 2;
1139 skeleton.skinText[where + 1] = 0;
1140 skeleton.skinText[where + 2] = 0;
1144 skeleton.drawmodel.textureptr.bind();
1147 bleedy = (1 + coordsy) * 512;
1148 bleedx = coordsx * 512;
1149 bleedy /= realtexdetail;
1150 bleedx /= realtexdetail;
1155 if (bleedx > skeleton.skinsize - 1)
1156 bleedx = skeleton.skinsize - 1;
1157 if (bleedy > skeleton.skinsize - 1)
1158 bleedy = skeleton.skinsize - 1;
1159 direction = abs(Random() % 2) * 2 - 1;
1164 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1165 deathbleeding += bleeding;
1166 bloodloss += bleeding * 3;
1168 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1169 if (abs(Random() % 2) == 0) {
1170 aitype = gethelptype;
1173 aitype = attacktypecutoff;
1184 * guessing this performs a reversal
1186 void Person::Reverse()
1188 if (!((victim->aitype == playercontrolled
1190 || staggerdelay <= 0)
1191 && victim->animTarget != jumpupanim
1192 && victim->animTarget != jumpdownanim
1193 && (!Tutorial::active || cananger)
1197 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1198 && (victim->id != 0 || difficulty >= 2)
1199 && (creature != wolftype || victim->creature == wolftype))
1202 if (animTarget == sweepanim) {
1203 animTarget = sweepreversedanim;
1204 animCurrent = sweepreversedanim;
1205 victim->animCurrent = sweepreversalanim;
1206 victim->animTarget = sweepreversalanim;
1208 if (animTarget == spinkickanim) {
1209 animTarget = spinkickreversedanim;
1210 animCurrent = spinkickreversedanim;
1211 victim->animCurrent = spinkickreversalanim;
1212 victim->animTarget = spinkickreversalanim;
1214 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1215 if (animTarget == rabbittacklinganim) {
1218 victim->frameCurrent = 6;
1219 victim->frameTarget = 7;
1221 animTarget = upunchreversedanim;
1222 animCurrent = upunchreversedanim;
1223 victim->animCurrent = upunchreversalanim;
1224 victim->animTarget = upunchreversalanim;
1226 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1227 if (victim->weaponactive != -1) {
1228 victim->throwtogglekeydown = 1;
1229 XYZ tempVelocity = victim->velocity * .2;
1230 if (tempVelocity.x == 0)
1231 tempVelocity.x = .1;
1232 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1233 victim->num_weapons--;
1234 if (victim->num_weapons) {
1235 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1236 if (victim->weaponstuck == victim->num_weapons)
1237 victim->weaponstuck = 0;
1240 victim->weaponactive = -1;
1241 for (unsigned j = 0; j < Person::players.size(); j++) {
1242 Person::players[j]->wentforweapon = 0;
1246 animTarget = staffhitreversedanim;
1247 animCurrent = staffhitreversedanim;
1248 victim->animCurrent = staffhitreversalanim;
1249 victim->animTarget = staffhitreversalanim;
1251 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1252 if (victim->weaponactive != -1) {
1253 victim->throwtogglekeydown = 1;
1254 XYZ tempVelocity = victim->velocity * .2;
1255 if (tempVelocity.x == 0)
1256 tempVelocity.x = .1;
1257 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1258 victim->num_weapons--;
1259 if (victim->num_weapons) {
1260 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1261 if (victim->weaponstuck == victim->num_weapons)
1262 victim->weaponstuck = 0;
1265 victim->weaponactive = -1;
1266 for (unsigned j = 0; j < Person::players.size(); j++) {
1267 Person::players[j]->wentforweapon = 0;
1270 animTarget = staffspinhitreversedanim;
1271 animCurrent = staffspinhitreversedanim;
1272 victim->animCurrent = staffspinhitreversalanim;
1273 victim->animTarget = staffspinhitreversalanim;
1275 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1276 if (victim->weaponactive != -1) {
1277 victim->throwtogglekeydown = 1;
1278 XYZ tempVelocity = victim->velocity * .2;
1279 if (tempVelocity.x == 0)
1280 tempVelocity.x = .1;
1281 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1282 victim->num_weapons--;
1283 if (victim->num_weapons) {
1284 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1285 if (victim->weaponstuck == victim->num_weapons)
1286 victim->weaponstuck = 0;
1289 victim->weaponactive = -1;
1290 for (unsigned j = 0; j < Person::players.size(); j++) {
1291 Person::players[j]->wentforweapon = 0;
1294 animTarget = swordslashreversedanim;
1295 animCurrent = swordslashreversedanim;
1296 victim->animCurrent = swordslashreversalanim;
1297 victim->animTarget = swordslashreversalanim;
1299 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1300 if (victim->weaponactive != -1) {
1301 victim->throwtogglekeydown = 1;
1302 XYZ tempVelocity = victim->velocity * .2;
1303 if (tempVelocity.x == 0)
1304 tempVelocity.x = .1;
1305 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1306 victim->num_weapons--;
1307 if (victim->num_weapons) {
1308 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1309 if (victim->weaponstuck == victim->num_weapons)
1310 victim->weaponstuck = 0;
1313 victim->weaponactive = -1;
1314 for (unsigned j = 0; j < Person::players.size(); j++) {
1315 Person::players[j]->wentforweapon = 0;
1318 animTarget = knifeslashreversedanim;
1319 animCurrent = knifeslashreversedanim;
1320 victim->animCurrent = knifeslashreversalanim;
1321 victim->animTarget = knifeslashreversalanim;
1323 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1324 victim->targettilt2 = targettilt2;
1325 victim->frameCurrent = frameCurrent;
1326 victim->frameTarget = frameTarget;
1327 victim->target = target;
1328 victim->velocity = 0;
1329 victim->oldcoords = victim->coords;
1330 victim->coords = coords;
1331 victim->targetyaw = targetyaw;
1332 victim->yaw = targetyaw;
1333 victim->victim = this->shared_from_this();
1335 if (animTarget == winduppunchanim) {
1336 animTarget = winduppunchblockedanim;
1337 victim->animTarget = blockhighleftanim;
1338 victim->frameTarget = 1;
1339 victim->target = .5;
1340 victim->victim = this->shared_from_this();
1341 victim->targetyaw = targetyaw + 180;
1343 if (animTarget == wolfslapanim) {
1344 animTarget = winduppunchblockedanim;
1345 victim->animTarget = blockhighleftanim;
1346 victim->frameTarget = 1;
1347 victim->target = .5;
1348 victim->victim = this->shared_from_this();
1349 victim->targetyaw = targetyaw + 180;
1351 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1352 animTarget = swordslashparriedanim;
1353 parriedrecently = .4;
1354 victim->parriedrecently = 0;
1355 victim->animTarget = swordslashparryanim;
1356 victim->frameTarget = 1;
1357 victim->target = .5;
1358 victim->victim = this->shared_from_this();
1359 victim->targetyaw = targetyaw + 180;
1361 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1362 if (victim->weaponactive != -1) {
1363 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1364 if (weapons[victim->weaponids[0]].getType() == staff)
1365 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1366 if (weapons[weaponids[0]].getType() == staff)
1367 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1368 emit_sound_at(swordstaffsound, victim->coords);
1370 emit_sound_at(metalhitsound, victim->coords);
1374 victim->Puff(righthand);
1376 victim->frameTarget = 0;
1377 victim->animTarget = staggerbackhighanim;
1378 victim->targetyaw = targetyaw + 180;
1380 aim = DoRotation(facing, 0, 90, 0) * 21;
1382 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1383 victim->num_weapons--;
1384 if (victim->num_weapons) {
1385 victim->weaponids[0] = victim->weaponids[num_weapons];
1386 if (victim->weaponstuck == victim->num_weapons)
1387 victim->weaponstuck = 0;
1389 victim->weaponactive = -1;
1390 for (unsigned i = 0; i < Person::players.size(); i++) {
1391 Person::players[i]->wentforweapon = 0;
1395 if (abs(Random() % 20) == 0) {
1396 if (weaponactive != -1) {
1397 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1398 if (weapons[victim->weaponids[0]].getType() == staff)
1399 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1400 if (weapons[weaponids[0]].getType() == staff)
1401 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1403 emit_sound_at(swordstaffsound, coords);
1405 emit_sound_at(metalhitsound, coords);
1413 animTarget = staggerbackhighanim;
1414 targetyaw = targetyaw + 180;
1416 aim = DoRotation(facing, 0, 90, 0) * 21;
1418 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1421 weaponids[0] = weaponids[num_weapons];
1422 if (weaponstuck == num_weapons)
1426 for (unsigned i = 0; i < Person::players.size(); i++) {
1427 Person::players[i]->wentforweapon = 0;
1434 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1435 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1436 victim->animTarget = dodgebackanim;
1437 victim->frameTarget = 0;
1441 rotatetarget = coords - victim->coords;
1442 Normalise(&rotatetarget);
1443 victim->targetyaw = -asin(0 - rotatetarget.x);
1444 victim->targetyaw *= 360 / 6.28;
1445 if (rotatetarget.z < 0)
1446 victim->targetyaw = 180 - victim->targetyaw;
1448 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1450 victim->lastattack3 = victim->lastattack2;
1451 victim->lastattack2 = victim->lastattack;
1452 victim->lastattack = victim->animTarget;
1454 victim->animTarget = sweepanim;
1455 victim->frameTarget = 0;
1459 rotatetarget = coords - victim->coords;
1460 Normalise(&rotatetarget);
1461 victim->targetyaw = -asin(0 - rotatetarget.x);
1462 victim->targetyaw *= 360 / 6.28;
1463 if (rotatetarget.z < 0)
1464 victim->targetyaw = 180 - victim->targetyaw;
1466 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1468 victim->lastattack3 = victim->lastattack2;
1469 victim->lastattack2 = victim->lastattack;
1470 victim->lastattack = victim->animTarget;
1475 victim->velocity = 0;
1477 if (aitype != playercontrolled) {
1479 if (escapednum < 2) {
1480 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1481 if ((Random() % chances) == 0) {
1487 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1494 void Person::DoDamage(float howmuch)
1498 damagetaken += howmuch / power;
1500 damagedealt += howmuch / power;
1504 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1509 if (!Tutorial::active) {
1510 damage += howmuch / power;
1511 permanentdamage += howmuch / 2 / power;
1512 superpermanentdamage += howmuch / 4 / power;
1515 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1517 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1521 camerashake += howmuch / 100;
1522 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1523 blackout = damage / damagetolerance;
1531 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile))
1532 aitype = attacktypecutoff;
1533 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1534 if (abs(Random() % 2) == 0) {
1535 aitype = gethelptype;
1538 aitype = attacktypecutoff;
1542 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1545 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1546 if (skeleton.free) {
1547 flatvelocity2 = skeleton.joints[i].velocity;
1548 flatfacing2 = skeleton.joints[i].position * scale + coords;
1550 flatvelocity2 = velocity;
1551 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1553 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1554 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1555 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1556 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1557 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1558 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1561 emit_sound_at(splattersound, coords);
1566 if (!dead && creature == wolftype) {
1567 award_bonus(0, Wolfbonus);
1574 if (!Tutorial::active || id == 0) {
1575 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1576 int whichsound = -1;
1578 if (creature == wolftype) {
1579 int i = abs(Random() % 2);
1581 whichsound = snarlsound;
1583 whichsound = snarl2sound;
1585 if (creature == rabbittype) {
1586 int i = abs(Random() % 2);
1588 whichsound = rabbitpainsound;
1589 if (i == 1 && damage > damagetolerance)
1590 whichsound = rabbitpain1sound;
1593 if (whichsound != -1) {
1594 emit_sound_at(whichsound, coords);
1595 addEnvSound(coords);
1603 * calculate/animate head facing direction?
1605 void Person::DoHead()
1607 static XYZ rotatearound;
1609 static float lookspeed = 500;
1611 if (!freeze && !winfreeze) {
1614 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1615 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1617 while (targetheadyaw > 180)targetheadyaw -= 360;
1618 while (targetheadyaw < -180)targetheadyaw += 360;
1620 if (targetheadyaw > 160)
1621 targetheadpitch = targetheadpitch * -1;
1622 if (targetheadyaw < -160)
1623 targetheadpitch = targetheadpitch * -1;
1624 if (targetheadyaw > 160)
1625 targetheadyaw = targetheadyaw - 180;
1626 if (targetheadyaw < -160)
1627 targetheadyaw = targetheadyaw + 180;
1629 if (targetheadpitch > 120)
1630 targetheadpitch = 120;
1631 if (targetheadpitch < -120)
1632 targetheadpitch = -120;
1633 if (targetheadyaw > 120)
1634 targetheadyaw = 120;
1635 if (targetheadyaw < -120)
1636 targetheadyaw = -120;
1639 targetheadpitch = 0;
1641 if (targetheadyaw > 80)
1643 if (targetheadyaw < -80)
1644 targetheadyaw = -80;
1645 if (targetheadpitch > 50)
1646 targetheadpitch = 50;
1647 if (targetheadpitch < -50)
1648 targetheadpitch = -50;
1651 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1652 headyaw = targetheadyaw;
1653 else if (headyaw > targetheadyaw) {
1654 headyaw -= multiplier * lookspeed;
1655 } else if (headyaw < targetheadyaw) {
1656 headyaw += multiplier * lookspeed;
1659 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1660 headpitch = targetheadpitch;
1661 else if (headpitch > targetheadpitch) {
1662 headpitch -= multiplier * lookspeed / 2;
1663 } else if (headpitch < targetheadpitch) {
1664 headpitch += multiplier * lookspeed / 2;
1667 rotatearound = jointPos(neck);
1668 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1672 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1673 facing = DoRotation(facing, headpitch * .4, 0, 0);
1674 facing = DoRotation(facing, 0, headyaw * .4, 0);
1677 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1678 facing = DoRotation(facing, headpitch * .8, 0, 0);
1679 facing = DoRotation(facing, 0, headyaw * .8, 0);
1682 if (animTarget == walkanim) {
1683 facing = DoRotation(facing, headpitch * .6, 0, 0);
1684 facing = DoRotation(facing, 0, headyaw * .6, 0);
1687 skeleton.specialforward[0] = facing;
1688 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1689 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1690 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1691 skeleton.FindRotationMuscle(i, animTarget);
1698 * ragdolls character?
1700 void Person::RagDoll(bool checkcollision)
1705 if (!skeleton.free) {
1708 if (id == 0 && isFlip())
1715 facing = DoRotation(facing, 0, yaw, 0);
1717 skeleton.freetime = 0;
1719 skeleton.longdead = 0;
1722 skeleton.broken = 0;
1723 skeleton.spinny = 1;
1725 skeleton.freefall = 1;
1727 if (!isnormal(velocity.x)) velocity.x = 0;
1728 if (!isnormal(velocity.y)) velocity.y = 0;
1729 if (!isnormal(velocity.z)) velocity.z = 0;
1730 if (!isnormal(yaw)) yaw = 0;
1731 if (!isnormal(coords.x)) coords = 0;
1732 if (!isnormal(tilt)) tilt = 0;
1733 if (!isnormal(tilt2)) tilt2 = 0;
1735 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1736 skeleton.joints[i].delay = 0;
1737 skeleton.joints[i].locked = 0;
1738 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1739 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1740 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1741 skeleton.joints[i].position.y += .1;
1742 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1743 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1746 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1747 skeleton.joints[i].velocity = 0;
1748 skeleton.joints[i].velchange = 0;
1750 skeleton.DoConstraints(&coords, &scale);
1751 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1752 skeleton.DoConstraints(&coords, &scale);
1753 skeleton.DoConstraints(&coords, &scale);
1754 skeleton.DoConstraints(&coords, &scale);
1755 skeleton.DoConstraints(&coords, &scale);
1758 speed = targetFrame().speed * 2;
1759 if (currentFrame().speed > targetFrame().speed) {
1760 speed = currentFrame().speed * 2;
1763 speed = transspeed * 2;
1767 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1768 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1769 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((targetFrame().joints[i].position - currentFrame().joints[i].position) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1771 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1772 change.x = (float)(Random() % 100) / 100;
1773 change.y = (float)(Random() % 100) / 100;
1774 change.z = (float)(Random() % 100) / 100;
1775 skeleton.joints[i].velocity += change;
1776 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1778 change.x = (float)(Random() % 100) / 100;
1779 change.y = (float)(Random() % 100) / 100;
1780 change.z = (float)(Random() % 100) / 100;
1781 skeleton.joints[i].velchange += change;
1782 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1785 if (checkcollision) {
1788 if (!skeleton.joints.empty()) {
1791 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1792 average += skeleton.joints[j].position;
1794 average /= skeleton.joints.size();
1795 coords += average * scale;
1796 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1797 skeleton.joints[j].position -= average;
1801 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1802 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1803 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1804 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1805 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1808 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1809 coords.x = lowpoint.x;
1810 coords.z = lowpoint.z;
1819 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1820 velocity += skeleton.joints[i].velocity * scale;
1822 velocity /= skeleton.joints.size();
1825 if (Random() % 2 == 0) {
1826 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1827 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1828 weapons[weaponids[0]].velocity.x += .01;
1831 weaponids[0] = weaponids[num_weapons];
1832 if (weaponstuck == num_weapons)
1836 for (unsigned i = 0; i < Person::players.size(); i++) {
1837 Person::players[i]->wentforweapon = 0;
1842 animTarget = bounceidleanim;
1843 animCurrent = bounceidleanim;
1853 void Person::FootLand(bodypart whichfoot, float opacity)
1855 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1856 cerr << "FootLand called on wrong bodypart" << endl;
1859 static XYZ terrainlight;
1860 static XYZ footvel, footpoint;
1861 if (opacity >= 1 || skiddelay <= 0) {
1864 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1865 if (distsq(&footpoint, &viewer))
1866 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1867 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1868 footvel = velocity / 5;
1871 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1872 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1873 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1874 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1875 if (environment == snowyenvironment) {
1876 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1878 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1880 } else if (environment == grassyenvironment) {
1881 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1882 } else if (environment == desertenvironment) {
1883 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1885 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1889 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1890 footvel = velocity / 5;
1893 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1894 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1895 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1902 * make a puff effect at a body part (dust effect?)
1904 void Person::Puff(int whichlabel)
1906 static XYZ footvel, footpoint;
1909 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1910 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1914 * I think I added this in an attempt to clean up code
1916 void Person::setTargetAnimation(int animation)
1918 animTarget = animation;
1927 void Person::DoAnimations()
1929 if (!skeleton.free) {
1930 static float oldtarget;
1932 if (isIdle() && animCurrent != getIdle())
1933 normalsupdatedelay = 0;
1935 if (animTarget == tempanim || animCurrent == tempanim) {
1936 Animation::animations[tempanim] = tempanimation;
1938 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1944 vel[0] = velocity.x;
1945 vel[1] = velocity.y;
1946 vel[2] = velocity.z;
1949 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
1950 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1952 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1954 if (!crouchkeydown && velocity.y >= -15)
1957 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1962 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1964 if (normaldotproduct(targfacing, velocity) >= -.3)
1965 animTarget = flipanim;
1967 animTarget = backflipanim;
1968 crouchtogglekeydown = 1;
1976 if (Animation::animations[animTarget].attack != reversed)
1978 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1979 crouchtogglekeydown = 0;
1980 if (aitype == playercontrolled)
1983 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1986 crouchtogglekeydown = 1;
1990 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1992 normalsupdatedelay = 0;
1996 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1998 emit_sound_at(fireendsound, coords);
1999 pause_sound(stream_firesound);
2003 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2004 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
2006 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2007 if (normaldotproduct(victim->facing, facing) > 0)
2008 victim->animTarget = rabbittackledbackanim;
2010 victim->animTarget = rabbittackledfrontanim;
2011 victim->frameTarget = 2;
2014 victim->targetyaw = yaw;
2015 if (victim->aitype == gethelptype)
2016 victim->DoDamage(victim->damagetolerance - victim->damage);
2017 //victim->DoDamage(30);
2018 if (creature == wolftype) {
2020 emit_sound_at(clawslicesound, victim->coords);
2022 victim->DoBloodBig(1 / victim->armorhead, 210);
2024 award_bonus(id, TackleBonus,
2025 victim->aitype == gethelptype ? 50 : 0);
2029 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2030 if (weapons[weaponids[0]].getType() == knife) {
2031 if (weaponactive == -1)
2033 else if (weaponactive == 0)
2036 if (weaponactive == -1) {
2037 emit_sound_at(knifesheathesound, coords);
2039 if (weaponactive != -1) {
2040 emit_sound_at(knifedrawsound, coords, 128);
2043 drawtogglekeydown = 1;
2046 if (!Tutorial::active || id == 0)
2047 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2048 int whichsound = -1;
2050 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2051 if (targetFrame().label == 1)
2052 whichsound = footstepsound;
2054 whichsound = footstepsound2;
2055 if (targetFrame().label == 1)
2056 FootLand(leftfoot, 1);
2057 if (targetFrame().label == 2)
2058 FootLand(rightfoot, 1);
2059 if (targetFrame().label == 3 && isRun()) {
2060 FootLand(rightfoot, 1);
2061 FootLand(leftfoot, 1);
2065 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2066 if (targetFrame().label == 1)
2067 whichsound = footstepsound3;
2069 whichsound = footstepsound4;
2073 if (targetFrame().label == 1)
2074 whichsound = footstepsound3;
2076 whichsound = footstepsound4;
2078 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2079 if (Animation::animations[animTarget].attack != neutral) {
2080 unsigned r = abs(Random() % 3);
2082 whichsound = lowwhooshsound;
2084 whichsound = midwhooshsound;
2086 whichsound = highwhooshsound;
2088 if (Animation::animations[animTarget].attack == neutral) {
2089 whichsound = movewhooshsound;
2091 } else if (targetFrame().label == 4) {
2092 whichsound = knifeswishsound;
2094 if (targetFrame().label == 8 && !Tutorial::active) {
2095 whichsound = landsound2;
2098 if (whichsound != -1) {
2099 emit_sound_at(whichsound, coords, 256.);
2102 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2103 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2104 addEnvSound(coords, 15);
2106 addEnvSound(coords, 6);
2111 if (targetFrame().label == 3) {
2113 emit_sound_at(whichsound, coords, 128.);
2119 if (!Tutorial::active || id == 0)
2120 if (speechdelay <= 0)
2121 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2122 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2123 int whichsound = -1;
2124 if (targetFrame().label == 4 && aitype != playercontrolled) {
2125 if (Animation::animations[animTarget].attack != neutral) {
2126 unsigned r = abs(Random() % 4);
2127 if (creature == rabbittype) {
2128 if (r == 0) whichsound = rabbitattacksound;
2129 if (r == 1) whichsound = rabbitattack2sound;
2130 if (r == 2) whichsound = rabbitattack3sound;
2131 if (r == 3) whichsound = rabbitattack4sound;
2133 if (creature == wolftype) {
2134 if (r == 0) whichsound = barksound;
2135 if (r == 1) whichsound = bark2sound;
2136 if (r == 2) whichsound = bark3sound;
2137 if (r == 3) whichsound = barkgrowlsound;
2143 if (whichsound != -1) {
2144 emit_sound_at(whichsound, coords);
2150 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2151 FootLand(leftfoot, 1);
2152 FootLand(rightfoot, 1);
2156 currentoffset = targetoffset;
2157 frameTarget = frameCurrent;
2158 animCurrent = animTarget;
2161 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2162 for (unsigned i = 0; i < weapons.size(); i++) {
2163 if (weapons[i].owner == -1)
2164 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2165 if (distsq(&coords, &weapons[i].position) >= 1) {
2166 if (weapons[i].getType() != staff) {
2167 emit_sound_at(knifedrawsound, coords, 128.);
2176 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2177 for (unsigned i = 0; i < weapons.size(); i++) {
2178 bool willwork = true;
2179 if (weapons[i].owner != -1)
2180 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2181 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2182 if (Person::players[weapons[i].owner]->num_weapons > 1)
2184 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2185 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2186 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2187 bool fleshstuck = false;
2188 if (weapons[i].owner != -1)
2189 if (victim->weaponstuck != -1) {
2190 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2195 emit_sound_at(fleshstabremovesound, coords, 128.);
2197 if (weapons[i].getType() != staff) {
2198 emit_sound_at(knifedrawsound, coords, 128.);
2201 if (weapons[i].owner != -1) {
2202 victim = Person::players[weapons[i].owner];
2203 if (victim->num_weapons == 1)
2204 victim->num_weapons = 0;
2206 victim->num_weapons = 1;
2208 //victim->weaponactive=-1;
2209 victim->skeleton.longdead = 0;
2210 victim->skeleton.free = 1;
2211 victim->skeleton.broken = 0;
2213 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2214 victim->skeleton.joints[j].velchange = 0;
2215 victim->skeleton.joints[j].locked = 0;
2221 Normalise(&relative);
2222 XYZ footvel, footpoint;
2224 footpoint = weapons[i].position;
2225 if (victim->weaponstuck != -1) {
2226 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2228 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2229 weapons[i].bloody = 2;
2230 weapons[i].blooddrip = 5;
2231 victim->weaponstuck = -1;
2234 if (victim->num_weapons > 0) {
2235 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2236 victim->weaponstuck = 0;
2237 if (victim->weaponids[0] == int(i))
2238 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2241 victim->jointVel(abdomen) += relative * 6;
2242 victim->jointVel(neck) += relative * 6;
2243 victim->jointVel(rightshoulder) += relative * 6;
2244 victim->jointVel(leftshoulder) += relative * 6;
2252 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2253 if (weaponactive == -1)
2255 else if (weaponactive == 0) {
2257 if (num_weapons == 2) {
2259 buffer = weaponids[0];
2260 weaponids[0] = weaponids[1];
2261 weaponids[1] = buffer;
2264 if (weaponactive == -1) {
2265 emit_sound_at(knifesheathesound, coords, 128.);
2267 if (weaponactive != -1) {
2268 emit_sound_at(knifedrawsound, coords, 128.);
2273 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2274 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2275 Normalise(&rotatetarget);
2276 targetyaw = -asin(0 - rotatetarget.x);
2277 targetyaw *= 360 / 6.28;
2278 if (rotatetarget.z < 0)
2279 targetyaw = 180 - targetyaw;
2281 if (animTarget == walljumprightkickanim)
2283 if (animTarget == walljumpleftkickanim)
2289 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2292 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2297 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2298 animTarget = rabbittackleanim;
2300 emit_sound_at(jumpsound, coords);
2308 targetloc = velocity;
2309 Normalise(&targetloc);
2310 targetloc += coords;
2311 for (unsigned i = 0; i < Person::players.size(); i++) {
2313 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2314 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2318 if (closestid != -1)
2319 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2321 victim = Person::players[closestid];
2322 coords = victim->coords;
2323 animCurrent = rabbittacklinganim;
2324 animTarget = rabbittacklinganim;
2328 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2329 rotatetarget = coords - victim->coords;
2330 Normalise(&rotatetarget);
2331 targetyaw = -asin(0 - rotatetarget.x);
2332 targetyaw *= 360 / 6.28;
2333 if (rotatetarget.z < 0)
2334 targetyaw = 180 - targetyaw;
2336 if (animTarget != rabbitrunninganim) {
2337 emit_sound_at(jumpsound, coords, 128.);
2343 float damagemult = 1 * power;
2344 if (creature == wolftype)
2345 damagemult = 2.5 * power;
2347 damagemult /= victim->damagetolerance / 200;
2349 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)) {
2350 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2351 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2355 if (Random() % 2 || creature == wolftype) {
2358 if (creature == wolftype)
2361 if (!Tutorial::active) {
2362 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2364 if (creature == wolftype) {
2365 emit_sound_at(clawslicesound, victim->coords, 128.);
2367 victim->DoBloodBig(2 / victim->armorhead, 175);
2371 relative = victim->coords - coords;
2373 Normalise(&relative);
2374 relative = DoRotation(relative, 0, -90, 0);
2375 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2376 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2378 victim->jointVel(head) += relative * damagemult * 200;
2380 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2386 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2387 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2391 if (Random() % 2 || creature == wolftype) {
2393 if (creature == wolftype)
2396 emit_sound_at(whooshhitsound, victim->coords);
2397 if (creature == wolftype) {
2398 emit_sound_at(clawslicesound, victim->coords, 128.);
2400 victim->DoBloodBig(2, 175);
2404 relative = victim->coords - coords;
2406 Normalise(&relative);
2408 Normalise(&relative);
2409 relative = DoRotation(relative, 0, 90, 0);
2410 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2411 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2413 victim->jointVel(head) += relative * damagemult * 100;
2415 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2419 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2420 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2426 if (!Tutorial::active) {
2427 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2429 if (creature == wolftype) {
2430 emit_sound_at(clawslicesound, victim->coords, 128.);
2432 victim->DoBloodBig(2 / victim->armorhead, 175);
2438 Normalise(&relative);
2439 relative = DoRotation(relative, 0, -90, 0);
2440 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2441 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2443 victim->jointVel(head) += relative * damagemult * 200;
2445 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2447 if (victim->damage > victim->damagetolerance)
2448 award_bonus(id, style);
2454 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2455 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2461 if (!Tutorial::active) {
2462 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2464 if (creature == wolftype) {
2465 emit_sound_at(clawslicesound, victim->coords, 128.);
2467 victim->DoBloodBig(2 / victim->armorhead, 175);
2473 Normalise(&relative);
2474 relative = DoRotation(relative, 0, 90, 0);
2475 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2476 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2478 victim->jointVel(head) += relative * damagemult * 200;
2480 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2482 if (victim->damage > victim->damagetolerance)
2483 award_bonus(id, style);
2489 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2490 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2498 emit_sound_at(whooshhitsound, victim->coords);
2501 relative = victim->coords - coords;
2503 Normalise(&relative);
2504 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2505 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2507 victim->jointVel(head) += relative * damagemult * 100;
2509 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2513 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2514 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2518 emit_sound_at(whooshhitsound, victim->coords, 128.);
2520 victim->skeleton.longdead = 0;
2521 victim->skeleton.free = 1;
2522 victim->skeleton.broken = 0;
2523 victim->skeleton.spinny = 1;
2525 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2526 victim->skeleton.joints[i].velchange = 0;
2527 victim->skeleton.joints[i].delay = 0;
2528 victim->skeleton.joints[i].locked = 0;
2529 //victim->skeleton.joints[i].velocity=0;
2535 Normalise(&relative);
2536 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2537 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2538 victim->skeleton.joints[i].position.y += relative.y * .3;
2539 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2540 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2542 victim->Puff(abdomen);
2543 victim->jointVel(abdomen).y = relative.y * 400;
2547 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2548 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2552 if (!Tutorial::active) {
2553 emit_sound_at(heavyimpactsound, coords, 128.);
2556 relative = victim->coords - coords;
2558 Normalise(&relative);
2559 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2560 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2562 victim->Puff(abdomen);
2563 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2567 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2568 victim->jointVel(abdomen) += relative * damagemult * 300;
2572 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2573 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2577 if (!Tutorial::active) {
2578 emit_sound_at(thudsound, coords);
2581 victim->skeleton.longdead = 0;
2582 victim->skeleton.free = 1;
2583 victim->skeleton.broken = 0;
2584 victim->skeleton.spinny = 1;
2586 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2587 victim->skeleton.joints[i].velchange = 0;
2588 //victim->skeleton.joints[i].delay=0;
2589 victim->skeleton.joints[i].locked = 0;
2592 relative = victim->coords - coords;
2593 Normalise(&relative);
2595 Normalise(&relative);
2596 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2597 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2602 victim->Puff(abdomen);
2603 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2604 victim->jointVel(abdomen) += relative * damagemult * 200;
2613 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2616 if (!victim->skeleton.free)
2620 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2621 emit_sound_at(knifesheathesound, coords, 128.);
2624 if (victim && hasvictim) {
2625 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2627 XYZ where, startpoint, endpoint, movepoint, colpoint;
2628 float rotationpoint;
2630 if (weapons[weaponids[weaponactive]].getType() == knife) {
2631 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2632 where -= victim->coords;
2633 if (!victim->skeleton.free)
2634 where = DoRotation(where, 0, -victim->yaw, 0);
2637 startpoint.y += 100;
2641 if (weapons[weaponids[weaponactive]].getType() == sword) {
2642 where = weapons[weaponids[weaponactive]].position;
2643 where -= victim->coords;
2644 if (!victim->skeleton.free)
2645 where = DoRotation(where, 0, -victim->yaw, 0);
2647 where = weapons[weaponids[weaponactive]].tippoint;
2648 where -= victim->coords;
2649 if (!victim->skeleton.free)
2650 where = DoRotation(where, 0, -victim->yaw, 0);
2653 if (weapons[weaponids[weaponactive]].getType() == staff) {
2654 where = weapons[weaponids[weaponactive]].position;
2655 where -= victim->coords;
2656 if (!victim->skeleton.free)
2657 where = DoRotation(where, 0, -victim->yaw, 0);
2659 where = weapons[weaponids[weaponactive]].tippoint;
2660 where -= victim->coords;
2661 if (!victim->skeleton.free)
2662 where = DoRotation(where, 0, -victim->yaw, 0);
2667 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2669 if (whichtri != -1) {
2670 if (victim->dead != 2) {
2671 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2673 award_bonus(id, FinishedBonus);
2676 weapons[weaponids[weaponactive]].bloody = 2;
2678 victim->skeleton.longdead = 0;
2679 victim->skeleton.free = 1;
2680 victim->skeleton.broken = 0;
2682 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2683 victim->skeleton.joints[i].velchange = 0;
2684 victim->skeleton.joints[i].locked = 0;
2685 //victim->skeleton.joints[i].velocity=0;
2687 emit_sound_at(fleshstabsound, coords, 128);
2690 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2691 weapons[weaponids[weaponactive]].blooddrip += 5;
2692 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2694 if (whichtri == -1) {
2696 emit_sound_at(knifesheathesound, coords, 128.);
2702 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2704 emit_sound_at(knifedrawsound, coords, 128);
2707 if (victim && hasvictim) {
2708 XYZ footvel, footpoint;
2710 emit_sound_at(fleshstabremovesound, coords, 128.);
2713 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2715 if (weapons[weaponids[weaponactive]].getType() == sword) {
2716 XYZ where, startpoint, endpoint, movepoint;
2717 float rotationpoint;
2720 where = weapons[weaponids[weaponactive]].position;
2721 where -= victim->coords;
2722 if (!victim->skeleton.free)
2723 where = DoRotation(where, 0, -victim->yaw, 0);
2725 where = weapons[weaponids[weaponactive]].tippoint;
2726 where -= victim->coords;
2727 if (!victim->skeleton.free)
2728 where = DoRotation(where, 0, -victim->yaw, 0);
2733 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2734 footpoint += victim->coords;
2736 if (whichtri == -1) {
2737 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2740 if (weapons[weaponids[weaponactive]].getType() == staff) {
2741 XYZ where, startpoint, endpoint, movepoint;
2742 float rotationpoint;
2745 where = weapons[weaponids[weaponactive]].position;
2746 where -= victim->coords;
2747 if (!victim->skeleton.free)
2748 where = DoRotation(where, 0, -victim->yaw, 0);
2750 where = weapons[weaponids[weaponactive]].tippoint;
2751 where -= victim->coords;
2752 if (!victim->skeleton.free)
2753 where = DoRotation(where, 0, -victim->yaw, 0);
2758 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2759 footpoint += victim->coords;
2761 if (whichtri == -1) {
2762 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2765 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2767 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2768 victim->skeleton.longdead = 0;
2769 victim->skeleton.free = 1;
2770 victim->skeleton.broken = 0;
2772 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2773 victim->skeleton.joints[i].velchange = 0;
2774 victim->skeleton.joints[i].locked = 0;
2775 //victim->skeleton.joints[i].velocity=0;
2781 Normalise(&relative);
2782 //victim->Puff(abdomen);
2784 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2786 if (victim->bloodloss < victim->damagetolerance) {
2787 victim->bloodloss += 1000;
2791 victim->jointVel(abdomen) += relative * damagemult * 20;
2795 if (!hasvictim && onterrain) {
2796 weapons[weaponids[weaponactive]].bloody = 0;
2797 weapons[weaponids[weaponactive]].blooddrip = 0;
2801 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2802 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2810 if (!Tutorial::active) {
2811 emit_sound_at(heavyimpactsound, victim->coords, 128);
2816 relative = victim->coords - coords;
2818 Normalise(&relative);
2819 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2820 victim->skeleton.joints[i].velocity = relative * 30;
2822 victim->jointVel(head) += relative * damagemult * 150;
2824 victim->frameTarget = 0;
2825 victim->animTarget = staggerbackhardanim;
2826 victim->targetyaw = targetyaw + 180;
2828 victim->stunned = 1;
2831 victim->Puff(abdomen);
2832 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2839 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2840 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2844 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2845 if (!Tutorial::active) {
2846 emit_sound_at(thudsound, victim->coords);
2848 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2849 if (!Tutorial::active) {
2850 emit_sound_at(whooshhitsound, victim->coords);
2853 if (!Tutorial::active) {
2854 emit_sound_at(heavyimpactsound, victim->coords);
2858 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2861 relative = victim->coords - coords;
2863 Normalise(&relative);
2865 Normalise(&relative);
2866 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2867 victim->skeleton.joints[i].velocity = relative * 5;
2869 victim->jointVel(abdomen) += relative * damagemult * 400;
2871 victim->frameTarget = 0;
2872 victim->animTarget = staggerbackhardanim;
2873 victim->targetyaw = targetyaw + 180;
2875 victim->stunned = 1;
2877 victim->Puff(abdomen);
2878 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2884 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2885 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2886 if (victim->id == 0)
2888 emit_sound_at(landsound2, victim->coords);
2894 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2895 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2896 if (victim->id == 0)
2899 if (weaponactive != -1) {
2900 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2901 if (weapons[victim->weaponids[0]].getType() == staff)
2902 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2903 if (weapons[weaponids[0]].getType() == staff)
2904 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2906 emit_sound_at(swordstaffsound, victim->coords);
2908 emit_sound_at(metalhitsound, victim->coords);
2916 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2917 if (weaponactive != -1) {
2920 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);
2922 weapons[weaponids[0]].thrown(aim * 50);
2925 weaponids[0] = weaponids[num_weapons];
2931 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2933 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2935 if (!Tutorial::active) {
2936 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2939 award_bonus(id, Slicebonus);
2940 if (!Tutorial::active) {
2941 emit_sound_at(knifeslicesound, victim->coords);
2943 //victim->jointVel(abdomen)+=relative*damagemult*200;
2944 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2945 if (victim->id != 0 || difficulty == 2) {
2946 victim->frameTarget = 0;
2947 victim->animTarget = staggerbackhardanim;
2948 victim->targetyaw = targetyaw + 180;
2952 victim->lowreversaldelay = 0;
2953 victim->highreversaldelay = 0;
2954 if (aitype != playercontrolled)
2955 weaponmissdelay = .6;
2957 if (!Tutorial::active) {
2958 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
2959 weapons[weaponids[weaponactive]].bloody = 1;
2961 weapons[weaponids[weaponactive]].blooddrip += 3;
2964 XYZ footvel, footpoint;
2966 if (skeleton.free) {
2967 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2969 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2971 if (Tutorial::active) {
2972 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2975 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2977 footvel = DoRotation(facing, 0, 90, 0) * .8;
2978 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2979 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2980 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2981 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2983 victim->DoDamage(damagemult * 0);
2986 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2987 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2988 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2989 award_bonus(id, Slashbonus);
2991 if (!Tutorial::active) {
2992 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2993 victim->DoBloodBig(2 / victim->armorhigh, 190);
2995 victim->DoBloodBig(2 / victim->armorhigh, 185);
2996 victim->deathbleeding = 1;
2997 emit_sound_at(swordslicesound, victim->coords);
2998 victim->frameTarget = 0;
2999 victim->animTarget = staggerbackhardanim;
3000 victim->targetyaw = targetyaw + 180;
3002 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3003 weapons[weaponids[weaponactive]].bloody = 1;
3005 weapons[weaponids[weaponactive]].blooddrip += 3;
3007 float bloodlossamount;
3008 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3009 victim->bloodloss += bloodlossamount / victim->armorhigh;
3010 victim->DoDamage(damagemult * 0);
3012 XYZ footvel, footpoint;
3014 if (skeleton.free) {
3015 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3017 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3020 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3022 footvel = DoRotation(facing, 0, 90, 0) * .8;
3024 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3025 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3026 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3027 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3030 if (victim->weaponactive != -1) {
3031 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3032 if (weapons[victim->weaponids[0]].getType() == staff)
3033 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3034 if (weapons[weaponids[0]].getType() == staff)
3035 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3037 emit_sound_at(swordstaffsound, victim->coords);
3039 emit_sound_at(metalhitsound, victim->coords);
3045 victim->Puff(righthand);
3047 victim->frameTarget = 0;
3048 victim->animTarget = staggerbackhighanim;
3049 victim->targetyaw = targetyaw + 180;
3051 aim = DoRotation(facing, 0, 90, 0) * 21;
3053 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3054 victim->num_weapons--;
3055 if (victim->num_weapons) {
3056 victim->weaponids[0] = victim->weaponids[num_weapons];
3057 if (victim->weaponstuck == victim->num_weapons)
3058 victim->weaponstuck = 0;
3060 victim->weaponactive = -1;
3061 for (unsigned i = 0; i < Person::players.size(); i++) {
3062 Person::players[i]->wentforweapon = 0;
3069 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3070 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3071 if (!Tutorial::active) {
3072 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3076 if (Random() % 2 || creature == wolftype) {
3079 emit_sound_at(staffheadsound, victim->coords);
3083 relative = victim->coords - coords;
3085 Normalise(&relative);
3086 relative = DoRotation(relative, 0, 90, 0);
3088 Normalise(&relative);
3089 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3090 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3092 victim->jointVel(head) += relative * damagemult * 230;
3093 victim->jointVel(neck) += relative * damagemult * 230;
3095 if (!Tutorial::active) {
3096 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3098 award_bonus(id, solidhit, 30);
3103 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3104 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3105 if (!Tutorial::active) {
3106 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3110 if (Random() % 2 || creature == wolftype) {
3113 emit_sound_at(staffheadsound, victim->coords);
3117 relative = victim->coords - coords;
3119 Normalise(&relative);
3120 relative = DoRotation(relative, 0, -90, 0);
3121 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3122 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3124 victim->jointVel(head) += relative * damagemult * 220;
3125 victim->jointVel(neck) += relative * damagemult * 220;
3127 if (!Tutorial::active) {
3128 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3130 award_bonus(id, solidhit, 60);
3135 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3136 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3138 if (!Tutorial::active) {
3140 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3143 if (Random() % 2 || creature == wolftype) {
3146 emit_sound_at(staffbodysound, victim->coords);
3148 victim->skeleton.longdead = 0;
3149 victim->skeleton.free = 1;
3150 victim->skeleton.broken = 0;
3152 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3153 victim->skeleton.joints[i].velchange = 0;
3154 victim->skeleton.joints[i].locked = 0;
3155 //victim->skeleton.joints[i].velocity=0;
3162 Normalise(&relative);
3163 if (!victim->dead) {
3164 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3165 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3167 victim->jointVel(abdomen) += relative * damagemult * 40;
3170 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3171 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3174 victim->Puff(abdomen);
3175 if (!Tutorial::active) {
3176 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3178 if (!victim->dead) {
3179 award_bonus(id, solidhit, 40);
3185 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3186 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3191 relative = victim->coords - coords;
3193 Normalise(&relative);
3197 if (Animation::animations[victim->animTarget].height == lowheight) {
3203 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3204 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3206 victim->jointVel(head) += relative * damagemult * 200;
3207 if (!Tutorial::active) {
3208 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3211 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3212 if (victim->howactive == typesleeping)
3213 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3214 if (creature == wolftype) {
3215 emit_sound_at(clawslicesound, victim->coords, 128.);
3217 victim->DoBloodBig(2 / victim->armorhead, 175);
3220 if (victim->damage >= victim->damagetolerance)
3222 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3223 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3225 victim->jointVel(abdomen) += relative * damagemult * 200;
3226 victim->frameTarget = 0;
3227 victim->animTarget = staggerbackhighanim;
3228 victim->targetyaw = targetyaw + 180;
3230 if (!Tutorial::active) {
3231 emit_sound_at(landsound2, victim->coords, 128.);
3233 victim->Puff(abdomen);
3234 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3235 if (creature == wolftype) {
3236 emit_sound_at(clawslicesound, victim->coords, 128.);
3238 victim->DoBloodBig(2 / victim->armorhigh, 170);
3245 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3246 if ((victim->animTarget != jumpupanim) &&
3247 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3248 (victim != this->shared_from_this())) {
3252 if (!Tutorial::active) {
3253 emit_sound_at(landsound2, victim->coords, 128.);
3256 relative = victim->coords - coords;
3258 Normalise(&relative);
3260 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3263 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3264 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3266 relative = DoRotation(relative, 0, -90, 0);
3268 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3269 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)
3270 victim->skeleton.joints[i].velocity = relative * 80;
3272 victim->Puff(rightankle);
3273 victim->Puff(leftankle);
3274 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3276 if (victim->damage >= victim->damagetolerance)
3278 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3279 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3281 relative = DoRotation(relative, 0, -90, 0);
3282 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3283 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)
3284 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3286 victim->jointVel(abdomen) += relative * damagemult * 200;
3287 victim->frameTarget = 0;
3288 victim->animTarget = staggerbackhighanim;
3289 victim->targetyaw = targetyaw + 180;
3291 if (!Tutorial::active) {
3292 emit_sound_at(landsound2, victim->coords, 128.);
3294 victim->Puff(abdomen);
3295 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3303 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3304 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3312 if (!Tutorial::active) {
3313 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3315 if (creature == wolftype) {
3316 emit_sound_at(clawslicesound, victim->coords, 128);
3318 victim->DoBloodBig(2 / victim->armorhigh, 170);
3322 relative = victim->coords - oldcoords;
3324 Normalise(&relative);
3325 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3326 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3328 victim->jointVel(abdomen) += relative * damagemult * 200;
3329 victim->Puff(abdomen);
3330 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3332 award_bonus(id, Reversal);
3335 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3336 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3337 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3338 takeWeapon(victim->weaponids[victim->weaponactive]);
3339 victim->num_weapons--;
3340 if (victim->num_weapons > 0) {
3341 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3343 victim->weaponactive = -1;
3348 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3356 emit_sound_at(whooshhitsound, victim->coords, 128.);
3359 relative = victim->coords - oldcoords;
3361 Normalise(&relative);
3362 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3363 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3365 victim->jointVel(abdomen) += relative * damagemult * 200;
3367 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3370 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3379 award_bonus(id, staffreversebonus);
3381 if (!Tutorial::active) {
3382 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3385 award_bonus(id, staffreversebonus); // Huh, again?
3388 relative = victim->coords - oldcoords;
3390 Normalise(&relative);
3391 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3392 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3394 victim->jointVel(abdomen) += relative * damagemult * 200;
3396 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3399 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3405 Normalise(&relative);
3407 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3408 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3410 victim->jointVel(lefthand) *= .1;
3411 victim->jointVel(leftwrist) *= .2;
3412 victim->jointVel(leftelbow) *= .5;
3413 victim->jointVel(leftshoulder) *= .7;
3414 victim->jointVel(righthand) *= .1;
3415 victim->jointVel(rightwrist) *= .2;
3416 victim->jointVel(rightelbow) *= .5;
3417 victim->jointVel(rightshoulder) *= .7;
3419 victim->Puff(abdomen);
3420 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3422 award_bonus(id, Reversal);
3426 if (weaponactive != -1 || creature == wolftype)
3428 if (creature == rabbittype && weaponactive != -1)
3429 if (weapons[weaponids[0]].getType() == staff)
3432 if (weaponactive != -1) {
3433 victim->DoBloodBig(2 / victim->armorhigh, 225);
3434 emit_sound_at(knifeslicesound, victim->coords);
3435 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3436 weapons[weaponids[weaponactive]].bloody = 1;
3437 weapons[weaponids[weaponactive]].blooddrip += 3;
3439 if (weaponactive == -1 && creature == wolftype) {
3440 emit_sound_at(clawslicesound, victim->coords, 128.);
3442 victim->DoBloodBig(2 / victim->armorhigh, 175);
3449 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3455 Normalise(&relative);
3457 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3458 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3460 victim->jointVel(lefthand) *= .1 - 1;
3461 victim->jointVel(leftwrist) *= .2 - 1;
3462 victim->jointVel(leftelbow) *= .5 - 1;
3463 victim->jointVel(leftshoulder) *= .7 - 1;
3464 victim->jointVel(righthand) *= .1 - 1;
3465 victim->jointVel(rightwrist) *= .2 - 1;
3466 victim->jointVel(rightelbow) *= .5 - 1;
3467 victim->jointVel(rightshoulder) *= .7 - 1;
3469 award_bonus(id, swordreversebonus);
3472 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3480 if (!Tutorial::active) {
3481 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3485 relative = victim->coords - oldcoords;
3487 Normalise(&relative);
3488 relative = DoRotation(relative, 0, -90, 0);
3489 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3490 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3492 victim->jointVel(abdomen) += relative * damagemult * 200;
3493 victim->Puff(abdomen);
3494 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3496 award_bonus(id, Reversal);
3499 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3502 victim->skeleton.spinny = 0;
3504 relative = facing * -1;
3506 Normalise(&relative);
3507 if (victim->id == 0)
3509 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3510 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3512 victim->damage = victim->damagetolerance;
3513 victim->permanentdamage = victim->damagetolerance - 1;
3516 if (weaponactive != -1 || creature == wolftype)
3518 if (creature == rabbittype && weaponactive != -1)
3519 if (weapons[weaponids[0]].getType() == staff)
3522 if (weaponactive != -1) {
3523 victim->DoBloodBig(200, 225);
3524 emit_sound_at(knifeslicesound, victim->coords);
3526 weapons[weaponids[weaponactive]].bloody = 2;
3527 weapons[weaponids[weaponactive]].blooddrip += 5;
3530 if (creature == wolftype && weaponactive == -1) {
3531 emit_sound_at(clawslicesound, victim->coords, 128.);
3533 victim->DoBloodBig(2, 175);
3536 award_bonus(id, spinecrusher);
3539 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3540 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3542 if (animTarget == knifefollowanim)
3543 victim->DoBloodBig(200, 210);
3544 if (animTarget == knifesneakattackanim) {
3545 XYZ footvel, footpoint;
3547 footpoint = weapons[weaponids[0]].tippoint;
3549 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3550 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3551 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3552 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3553 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3554 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3555 victim->DoBloodBig(200, 195);
3556 award_bonus(id, tracheotomy);
3558 if (animTarget == knifefollowanim) {
3559 award_bonus(id, Stabbonus);
3560 XYZ footvel, footpoint;
3562 footpoint = weapons[weaponids[0]].tippoint;
3564 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3565 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3566 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3567 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3568 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3569 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3572 victim->bloodloss += 10000;
3573 victim->velocity = 0;
3574 emit_sound_at(fleshstabsound, victim->coords);
3576 weapons[weaponids[weaponactive]].bloody = 2;
3577 weapons[weaponids[weaponactive]].blooddrip += 5;
3581 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3583 victim->velocity = 0;
3584 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3585 victim->skeleton.joints[i].velocity = 0;
3587 if (animTarget == knifefollowanim) {
3589 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3590 victim->skeleton.joints[i].velocity = 0;
3593 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3594 emit_sound_at(fleshstabremovesound, victim->coords);
3596 weapons[weaponids[weaponactive]].bloody = 2;
3597 weapons[weaponids[weaponactive]].blooddrip += 5;
3599 XYZ footvel, footpoint;
3601 footpoint = weapons[weaponids[0]].tippoint;
3603 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3604 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3605 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3606 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3607 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3608 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3612 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3613 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3614 award_bonus(id, backstab);
3618 XYZ footvel, footpoint;
3620 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3622 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3623 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3624 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3625 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3626 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3627 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3628 victim->DoBloodBig(200, 180);
3629 victim->DoBloodBig(200, 215);
3630 victim->bloodloss += 10000;
3631 victim->velocity = 0;
3632 emit_sound_at(fleshstabsound, victim->coords);
3634 weapons[weaponids[weaponactive]].bloody = 2;
3635 weapons[weaponids[weaponactive]].blooddrip += 5;
3639 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3641 victim->velocity = 0;
3642 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3643 victim->skeleton.joints[i].velocity = 0;
3645 if (weaponactive != -1) {
3646 emit_sound_at(fleshstabremovesound, victim->coords);
3648 weapons[weaponids[weaponactive]].bloody = 2;
3649 weapons[weaponids[weaponactive]].blooddrip += 5;
3651 XYZ footvel, footpoint;
3653 footpoint = weapons[weaponids[0]].tippoint;
3655 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3656 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3657 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3658 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3659 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3660 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3664 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3672 if (weaponactive == -1) {
3673 if (!Tutorial::active) {
3674 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3679 if (weaponactive != -1 || creature == wolftype)
3681 if (creature == rabbittype && weaponactive != -1)
3682 if (weapons[weaponids[0]].getType() == staff)
3685 if (weaponactive != -1) {
3686 victim->DoBloodBig(2 / victim->armorhead, 225);
3687 emit_sound_at(knifeslicesound, victim->coords);
3688 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3689 weapons[weaponids[weaponactive]].bloody = 1;
3690 weapons[weaponids[weaponactive]].blooddrip += 3;
3692 if (weaponactive == -1 && creature == wolftype) {
3693 emit_sound_at(clawslicesound, victim->coords, 128.);
3695 victim->DoBloodBig(2 / victim->armorhead, 175);
3699 award_bonus(id, Reversal);
3704 relative = facing * -1;
3706 Normalise(&relative);
3707 relative = DoRotation(relative, 0, 90, 0);
3709 Normalise(&relative);
3710 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3711 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3713 victim->jointVel(head) += relative * damagemult * 200;
3714 if (victim->damage < victim->damagetolerance - 100)
3715 victim->velocity = relative * 200;
3716 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3717 victim->velocity = 0;
3720 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))) {
3724 relative = facing * -1;
3726 Normalise(&relative);
3727 relative = DoRotation(relative, 0, 90, 0);
3729 Normalise(&relative);
3730 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3731 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3733 victim->jointVel(head) += relative * damagemult * 200;
3736 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3737 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3738 award_bonus(id, reverseko);
3744 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3747 animTarget = getIdle();
3748 FootLand(leftfoot, 1);
3749 FootLand(rightfoot, 1);
3751 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3752 animTarget = rollanim;
3754 emit_sound_at(movewhooshsound, coords, 128.);
3756 if (animCurrent == staggerbackhighanim) {
3757 animTarget = getIdle();
3759 if (animCurrent == staggerbackhardanim) {
3760 animTarget = getIdle();
3762 if (animCurrent == removeknifeanim) {
3763 animTarget = getIdle();
3765 if (animCurrent == crouchremoveknifeanim) {
3766 animTarget = getCrouch();
3768 if (animCurrent == backhandspringanim) {
3769 animTarget = getIdle();
3771 if (animCurrent == dodgebackanim) {
3772 animTarget = getIdle();
3774 if (animCurrent == drawleftanim) {
3775 animTarget = getIdle();
3777 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3778 animTarget = getIdle();
3779 if (animCurrent == crouchdrawrightanim) {
3780 animTarget = getCrouch();
3782 if (weaponactive == -1)
3784 else if (weaponactive == 0) {
3786 if (num_weapons == 2) {
3788 buffer = weaponids[0];
3789 weaponids[0] = weaponids[1];
3790 weaponids[1] = buffer;
3794 if (weaponactive == -1) {
3795 emit_sound_at(knifesheathesound, coords, 128.);
3797 if (weaponactive != -1) {
3798 emit_sound_at(knifedrawsound, coords, 128.);
3801 if (animCurrent == rollanim) {
3802 animTarget = getCrouch();
3803 FootLand(leftfoot, 1);
3804 FootLand(rightfoot, 1);
3807 if (animTarget == walljumprightkickanim) {
3810 if (animTarget == walljumpleftkickanim) {
3813 animTarget = jumpdownanim;
3815 if (animCurrent == climbanim) {
3816 animTarget = getCrouch();
3818 coords += facing * .1;
3819 if (!isnormal(coords.x))
3829 if (animTarget == rabbitkickreversalanim) {
3830 animTarget = getCrouch();
3833 if (animTarget == jumpreversalanim) {
3834 animTarget = getCrouch();
3837 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3838 if (attackkeydown && animTarget != walljumpfrontanim) {
3840 float closestdist = -1;
3842 if (Person::players.size() > 1)
3843 for (unsigned i = 0; i < Person::players.size(); i++) {
3844 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3845 distance = distsq(&Person::players[i]->coords, &coords);
3846 if (closestdist == -1 || distance < closestdist) {
3847 closestdist = distance;
3852 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3853 victim = Person::players[closest];
3854 animTarget = walljumprightkickanim;
3856 XYZ rotatetarget = victim->coords - coords;
3857 Normalise(&rotatetarget);
3858 yaw = -asin(0 - rotatetarget.x);
3860 if (rotatetarget.z < 0)
3862 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3863 velocity = (victim->coords - coords) * 4;
3868 if (animTarget == walljumpbackanim) {
3869 animTarget = backflipanim;
3871 velocity = facing * -8;
3874 resume_stream(whooshsound);
3876 if (animTarget == walljumprightanim) {
3877 animTarget = rightflipanim;
3881 velocity = DoRotation(facing, 0, 30, 0) * -8;
3884 if (animTarget == walljumpfrontanim) {
3885 animTarget = frontflipanim;
3889 velocity = facing * 8;
3893 resume_stream(whooshsound);
3895 if (animTarget == walljumpleftanim) {
3896 if (attackkeydown) {
3898 float closestdist = -1;
3900 if (Person::players.size() > 1)
3901 for (unsigned i = 0; i < Person::players.size(); i++) {
3902 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3903 distance = distsq(&Person::players[i]->coords, &coords);
3904 if (closestdist == -1 || distance < closestdist) {
3905 closestdist = distance;
3910 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3911 victim = Person::players[closest];
3912 animTarget = walljumpleftkickanim;
3914 XYZ rotatetarget = victim->coords - coords;
3915 Normalise(&rotatetarget);
3916 yaw = -asin(0 - rotatetarget.x);
3918 if (rotatetarget.z < 0)
3920 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3921 velocity = (victim->coords - coords) * 4;
3926 if (animTarget != walljumpleftkickanim) {
3927 animTarget = leftflipanim;
3931 velocity = DoRotation(facing, 0, -30, 0) * -8;
3935 resume_stream(whooshsound);
3937 if (animTarget == sneakattackanim) {
3938 animCurrent = getCrouch();
3939 animTarget = getCrouch();
3946 transspeed = 1000000;
3947 targetheadyaw += 180;
3948 coords -= facing * .7;
3950 coords.y = terrain.getHeight(coords.x, coords.z);
3954 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3955 animTarget = getIdle();
3958 coords.y = terrain.getHeight(coords.x, coords.z);
3962 if (animCurrent == knifefollowanim) {
3963 animTarget = getIdle();
3966 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3967 float ycoords = oldcoords.y;
3968 animTarget = getStop();
3973 transspeed = 1000000;
3974 targetheadyaw += 180;
3975 if (!isnormal(coords.x))
3977 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3978 oldcoords = coords + facing * .5;
3979 else if (animCurrent == sweepreversalanim)
3980 oldcoords = coords + facing * 1.1;
3981 else if (animCurrent == upunchreversalanim) {
3982 oldcoords = coords + facing * 1.5;
3985 targetheadyaw += 180;
3988 } else if (animCurrent == knifeslashreversalanim) {
3989 oldcoords = coords + facing * .5;
3992 targetheadyaw += 90;
3995 } else if (animCurrent == staffspinhitreversalanim) {
3998 targetheadyaw += 180;
4003 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4005 oldcoords.y = ycoords;
4006 currentoffset = coords - oldcoords;
4012 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4017 if (Animation::animations[animTarget].attack == reversed) {
4019 if (animTarget == sweepreversedanim)
4021 animTarget = backhandspringanim;
4023 emit_sound_at(landsound, coords, 128);
4025 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4026 animTarget = rollanim;
4029 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4030 coords.y = oldcoords.y;
4032 if (animCurrent == knifeslashreversedanim) {
4033 animTarget = rollanim;
4038 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4039 coords.y = oldcoords.y;
4043 animTarget = jumpdownanim;
4046 animTarget = getIdle();
4048 animTarget = getIdle();
4049 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4050 animTarget = getIdle();
4052 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4053 coords.y = oldcoords.y;
4054 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4055 targetoffset.y = coords.y;
4057 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4058 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4059 currentoffset.y -= (coords.y - targetoffset.y);
4060 coords.y = targetoffset.y;
4062 normalsupdatedelay = 0;
4064 if (animCurrent == upunchanim) {
4065 animTarget = getStop();
4066 normalsupdatedelay = 0;
4069 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4073 if (num_weapons > 0)
4074 if (weapons[0].getType() == staff)
4080 rabbitkickragdoll = 1;
4082 if (animCurrent == rabbitkickreversedanim) {
4088 skeleton.spinny = 0;
4089 SolidHitBonus(!id); // FIXME: tricky id
4093 animTarget = rollanim;
4096 pause_sound(whooshsound);
4100 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4104 skeleton.spinny = 0;
4106 if (animCurrent == jumpreversedanim) {
4112 skeleton.spinny = 0;
4113 SolidHitBonus(!id); // FIXME: tricky id
4117 animTarget = rollanim;
4118 coords += facing * 2;
4120 pause_sound(whooshsound);
4125 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) {
4126 animTarget = getupfromfrontanim;
4128 } else if (Animation::animations[animCurrent].attack == normalattack) {
4129 animTarget = getIdle();
4132 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4133 animTarget = blockhighleftstrikeanim;
4135 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4136 animTarget = getIdle();
4139 if (animCurrent == spinkickanim && victim->skeleton.free) {
4140 if (creature == rabbittype)
4141 animTarget = fightidleanim;
4146 if (isIdle() && !wasIdle())
4147 normalsupdatedelay = 0;
4149 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4150 animTarget = jumpdownanim;
4153 if (!skeleton.free) {
4155 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4156 if (!isRun() || !wasRun()) {
4157 if (targetFrame().speed > currentFrame().speed)
4158 target += multiplier * targetFrame().speed * speed * 2;
4159 if (targetFrame().speed <= currentFrame().speed)
4160 target += multiplier * currentFrame().speed * speed * 2;
4162 if (isRun() && wasRun()) {
4164 tempspeed = velspeed;
4165 if (tempspeed < 10 * speedmult)
4166 tempspeed = 10 * speedmult;
4167 /* FIXME - mixed of target and current here, is that intended? */
4168 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4170 } else if (transspeed)
4171 target += multiplier * transspeed * speed * 2;
4173 if (!isRun() || !wasRun()) {
4174 if (targetFrame().speed > currentFrame().speed)
4175 target += multiplier * targetFrame().speed * 2;
4176 if (targetFrame().speed <= currentFrame().speed)
4177 target += multiplier * currentFrame().speed * 2;
4181 if (animCurrent != animTarget)
4182 target = (target + oldtarget) / 2;
4185 frameCurrent = frameTarget;
4189 rot = targetrot * target;
4190 yaw += rot - oldrot;
4196 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4197 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4199 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4201 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4202 skeleton.joints[i].position = currentFrame().joints[i].position;
4205 skeleton.FindForwards();
4207 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4208 if (skeleton.muscles[i].visible) {
4209 skeleton.FindRotationMuscle(i, animTarget);
4212 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4213 if (skeleton.muscles[i].visible) {
4214 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4215 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4216 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4217 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4218 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4219 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4224 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4225 skeleton.joints[i].position = targetFrame().joints[i].position;
4228 skeleton.FindForwards();
4230 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4231 if (skeleton.muscles[i].visible) {
4232 skeleton.FindRotationMuscle(i, animTarget);
4235 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4236 if (skeleton.muscles[i].visible) {
4237 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4238 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4239 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4240 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4241 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4242 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4243 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4244 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4245 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4246 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4247 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4248 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4253 oldanimCurrent = animCurrent;
4254 oldanimTarget = animTarget;
4255 oldframeTarget = frameTarget;
4256 oldframeCurrent = frameCurrent;
4258 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4259 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4260 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4262 offset = currentoffset * (1 - target) + targetoffset * target;
4263 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4264 if (skeleton.muscles[i].visible) {
4265 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4266 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4267 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4272 if (isLanding() && landhard) {
4275 animTarget = getLandhard();
4288 void Person::DoStuff()
4290 static XYZ terrainnormal;
4291 static XYZ flatfacing;
4292 static XYZ flatvelocity;
4293 static float flatvelspeed;
4295 static int bloodsize;
4296 static int startx, starty, endx, endy;
4297 static GLubyte color;
4298 static XYZ bloodvel;
4300 onfiredelay -= multiplier;
4301 if (onfiredelay < 0 && onfire) {
4302 if (Random() % 2 == 0) {
4308 crouchkeydowntime += multiplier;
4310 crouchkeydowntime = 0;
4311 jumpkeydowntime += multiplier;
4312 if (!jumpkeydown && skeleton.free)
4313 jumpkeydowntime = 0;
4315 if (hostile || damage > 0 || bloodloss > 0)
4318 if (isIdle() || isRun())
4321 if (num_weapons == 1 && weaponactive != -1)
4325 blooddimamount -= multiplier * .3;
4326 speechdelay -= multiplier;
4327 texupdatedelay -= multiplier;
4328 interestdelay -= multiplier;
4329 flamedelay -= multiplier;
4330 parriedrecently -= multiplier;
4332 victim = this->shared_from_this();
4337 speed = 1.1 * speedmult;
4339 speed = 1.0 * speedmult;
4341 rabbitkickragdoll = 0;
4345 if (id != 0 && (creature == rabbittype || difficulty != 2))
4347 if (id != 0 && creature == wolftype && difficulty == 2) {
4349 if (aitype != passivetype) {
4351 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) {
4357 if (animTarget == wolfrunninganim && !superruntoggle) {
4358 animTarget = getRun();
4362 if (weaponactive == -1 && num_weapons > 0) {
4363 if (weapons[weaponids[0]].getType() == staff) {
4369 burnt += multiplier;
4373 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4375 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4381 vel[0] = velocity.x;
4382 vel[1] = velocity.y;
4383 vel[2] = velocity.z;
4386 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4387 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4391 while (flamedelay < 0 && onfire) {
4393 int howmany = fabs(Random() % (skeleton.joints.size()));
4394 if (skeleton.free) {
4395 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4396 flatfacing = skeleton.joints[howmany].position * scale + coords;
4398 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4399 flatvelocity = (coords - oldcoords) / multiplier / 2;
4401 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4404 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4406 int howmany = fabs(Random() % (skeleton.joints.size()));
4407 if (skeleton.free) {
4408 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4409 flatfacing = skeleton.joints[howmany].position * scale + coords;
4411 flatvelocity = (coords - oldcoords) / multiplier / 2;
4412 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4414 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4418 bleeding -= multiplier * .3;
4419 if (bloodtoggle == 2) {
4420 skeleton.drawmodel.textureptr.bind();
4421 if ((bleeding <= 0) && (detail != 2))
4426 if (neckspurtamount > 0) {
4427 neckspurtamount -= multiplier;
4428 neckspurtdelay -= multiplier * 3;
4429 neckspurtparticledelay -= multiplier * 3;
4430 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4433 if (skeleton.free) {
4434 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4435 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4436 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4438 bloodvel.z = 5 * neckspurtamount;
4439 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4440 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4441 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4443 neckspurtparticledelay = .05;
4445 if (neckspurtdelay < 0) {
4450 if (deathbleeding > 0 && dead != 2) {
4451 if (deathbleeding < 5)
4452 bleeddelay -= deathbleeding * multiplier / 4;
4454 bleeddelay -= 5 * multiplier / 4;
4455 if (bleeddelay < 0 && bloodtoggle) {
4460 if (skeleton.free) {
4461 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4462 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4464 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4465 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4469 bloodloss += deathbleeding * multiplier * 80;
4470 deathbleeding -= multiplier * 1.6;
4471 if (deathbleeding < 0)
4473 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4474 if (weaponactive != -1) {
4475 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4476 weapons[weaponids[0]].velocity.x += .01;
4479 weaponids[0] = weaponids[num_weapons];
4480 if (weaponstuck == num_weapons)
4484 for (unsigned i = 0; i < Person::players.size(); i++) {
4485 Person::players[i]->wentforweapon = 0;
4493 if (!dead && creature == wolftype) {
4494 award_bonus(0, Wolfbonus);
4497 if (animTarget == knifefollowedanim && !skeleton.free) {
4498 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4499 skeleton.joints[i].velocity = 0;
4500 skeleton.joints[i].velocity.y = -2;
4503 if (id != 0 && unconscioustime > .1) {
4511 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4512 texupdatedelay = .12;
4514 bloodsize = 5 - realtexdetail;
4518 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4519 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4520 endx = startx + bloodsize;
4521 endy = starty + bloodsize;
4531 if (endx > skeleton.skinsize - 1) {
4532 endx = skeleton.skinsize - 1;
4535 if (endy > skeleton.skinsize - 1) {
4536 endy = skeleton.skinsize - 1;
4544 for (int i = startx; i < endx; i++) {
4545 for (int j = starty; j < endy; j++) {
4546 if (Random() % 2 == 0) {
4547 color = Random() % 85 + 170;
4548 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4549 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4550 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4551 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4556 skeleton.drawmodel.textureptr.bind();
4560 if (skeleton.free) {
4561 bleedx += 4 * direction / realtexdetail;
4563 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4565 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4567 bleedy -= 4 / realtexdetail;
4569 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4571 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4575 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4576 righthandmorphness = targetrighthandmorphness;
4577 righthandmorphstart = righthandmorphend;
4578 } else if (righthandmorphness > targetrighthandmorphness) {
4579 righthandmorphness -= multiplier * 4;
4580 } else if (righthandmorphness < targetrighthandmorphness) {
4581 righthandmorphness += multiplier * 4;
4584 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4585 lefthandmorphness = targetlefthandmorphness;
4586 lefthandmorphstart = lefthandmorphend;
4587 } else if (lefthandmorphness > targetlefthandmorphness) {
4588 lefthandmorphness -= multiplier * 4;
4589 } else if (lefthandmorphness < targetlefthandmorphness) {
4590 lefthandmorphness += multiplier * 4;
4593 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4594 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4595 tailmorphness = targettailmorphness;
4596 tailmorphstart = tailmorphend;
4597 } else if (tailmorphness > targettailmorphness) {
4598 tailmorphness -= multiplier * 10;
4599 } else if (tailmorphness < targettailmorphness) {
4600 tailmorphness += multiplier * 10;
4604 if (creature == wolftype) {
4605 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4606 tailmorphness = targettailmorphness;
4607 tailmorphstart = tailmorphend;
4608 } else if (tailmorphness > targettailmorphness) {
4609 tailmorphness -= multiplier * 2;
4610 } else if (tailmorphness < targettailmorphness) {
4611 tailmorphness += multiplier * 2;
4615 if (headmorphend == 3 || headmorphstart == 3) {
4616 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4617 headmorphness = targetheadmorphness;
4618 headmorphstart = headmorphend;
4619 } else if (headmorphness > targetheadmorphness) {
4620 headmorphness -= multiplier * 7;
4621 } else if (headmorphness < targetheadmorphness) {
4622 headmorphness += multiplier * 7;
4624 } else if (headmorphend == 5 || headmorphstart == 5) {
4625 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4626 headmorphness = targetheadmorphness;
4627 headmorphstart = headmorphend;
4628 } else if (headmorphness > targetheadmorphness) {
4629 headmorphness -= multiplier * 10;
4630 } else if (headmorphness < targetheadmorphness) {
4631 headmorphness += multiplier * 10;
4634 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4635 headmorphness = targetheadmorphness;
4636 headmorphstart = headmorphend;
4637 } else if (headmorphness > targetheadmorphness) {
4638 headmorphness -= multiplier * 4;
4639 } else if (headmorphness < targetheadmorphness) {
4640 headmorphness += multiplier * 4;
4644 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4645 chestmorphness = targetchestmorphness;
4646 chestmorphstart = chestmorphend;
4647 } else if (chestmorphness > targetchestmorphness) {
4648 chestmorphness -= multiplier;
4649 } else if (chestmorphness < targetchestmorphness) {
4650 chestmorphness += multiplier;
4653 if (dead != 2 && howactive <= typesleeping) {
4654 if (chestmorphstart == 0 && chestmorphend == 0) {
4656 targetchestmorphness = 1;
4659 if (chestmorphstart != 0 && chestmorphend != 0) {
4661 targetchestmorphness = 1;
4663 if (environment == snowyenvironment) {
4666 if (skeleton.free) {
4667 footvel = skeleton.specialforward[0] * -1;
4668 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4670 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4671 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4673 if (animTarget == sleepanim)
4674 footvel = DoRotation(footvel, 0, 90, 0);
4675 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4679 if (!dead && howactive < typesleeping) {
4680 blinkdelay -= multiplier * 2;
4681 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4683 targetheadmorphness = 1;
4685 blinkdelay = (float)(abs(Random() % 40)) / 5;
4687 if (headmorphstart == 3 && headmorphend == 3) {
4689 targetheadmorphness = 1;
4694 twitchdelay -= multiplier * 1.5;
4695 if (animTarget != hurtidleanim) {
4696 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4698 targetheadmorphness = 1;
4700 twitchdelay = (float)(abs(Random() % 40)) / 5;
4702 if (headmorphstart == 5 && headmorphend == 5) {
4704 targetheadmorphness = 1;
4708 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4709 twitchdelay3 -= multiplier * 1;
4710 if (Random() % 2 == 0) {
4711 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4712 righthandmorphness = 0;
4713 targetrighthandmorphness = 1;
4714 righthandmorphend = 1;
4715 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4717 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4718 righthandmorphness = 0;
4719 targetrighthandmorphness = 1;
4720 righthandmorphend = 0;
4723 if (Random() % 2 == 0) {
4724 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4725 lefthandmorphness = 0;
4726 targetlefthandmorphness = 1;
4727 lefthandmorphend = 1;
4728 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4730 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4731 lefthandmorphness = 0;
4732 targetlefthandmorphness = 1;
4733 lefthandmorphend = 0;
4739 if (creature == rabbittype) {
4740 if (howactive < typesleeping)
4741 twitchdelay2 -= multiplier * 1.5;
4743 twitchdelay2 -= multiplier * 0.5;
4744 if (howactive <= typesleeping) {
4745 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4747 targettailmorphness = 1;
4749 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4751 if (tailmorphstart == 1 && tailmorphend == 1) {
4753 targettailmorphness = 1;
4756 if (tailmorphstart == 2 && tailmorphend == 2) {
4758 targettailmorphness = 1;
4765 if (creature == wolftype) {
4766 twitchdelay2 -= multiplier * 1.5;
4767 if (tailmorphend != 0)
4768 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4770 targettailmorphness = 1;
4774 if (tailmorphend != 5)
4775 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4777 targettailmorphness = 1;
4781 if (twitchdelay2 <= 0) {
4782 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4784 targettailmorphness = 1;
4787 if (tailmorphstart == 1 && tailmorphend == 1) {
4789 targettailmorphness = 1;
4792 if (tailmorphstart == 2 && tailmorphend == 2) {
4794 targettailmorphness = 1;
4797 if (tailmorphstart == 3 && tailmorphend == 3) {
4799 targettailmorphness = 1;
4802 if (tailmorphstart == 4 && tailmorphend == 4) {
4804 targettailmorphness = 1;
4811 unconscioustime = 0;
4814 if (dead == 1 || howactive == typesleeping) {
4815 unconscioustime += multiplier;
4816 //If unconscious, close eyes and mouth
4817 if (righthandmorphend != 0)
4818 righthandmorphness = 0;
4819 righthandmorphend = 0;
4820 targetrighthandmorphness = 1;
4822 if (lefthandmorphend != 0)
4823 lefthandmorphness = 0;
4824 lefthandmorphend = 0;
4825 targetlefthandmorphness = 1;
4827 if (headmorphend != 3 && headmorphend != 5)
4830 targetheadmorphness = 1;
4834 if (howactive > typesleeping) {
4837 if (bloodtoggle && !bled) {
4838 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4840 if (bloodtoggle && !bled)
4841 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4842 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4843 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4847 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4852 if (dead == 2 || howactive > typesleeping) {
4853 //If dead, open mouth and hands
4854 if (righthandmorphend != 0)
4855 righthandmorphness = 0;
4856 righthandmorphend = 0;
4857 targetrighthandmorphness = 1;
4859 if (lefthandmorphend != 0)
4860 lefthandmorphness = 0;
4861 lefthandmorphend = 0;
4862 targetlefthandmorphness = 1;
4864 if (headmorphend != 2)
4867 targetheadmorphness = 1;
4870 if (stunned > 0 && !dead && headmorphend != 2) {
4871 if (headmorphend != 4)
4874 targetheadmorphness = 1;
4877 if (damage > damagetolerance && !dead) {
4880 unconscioustime = 0;
4882 if (creature == wolftype) {
4883 award_bonus(0, Wolfbonus);
4888 if (weaponactive != -1) {
4889 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4890 weapons[weaponids[0]].velocity.x += .01;
4893 weaponids[0] = weaponids[num_weapons];
4894 if (weaponstuck == num_weapons)
4898 for (unsigned i = 0; i < Person::players.size(); i++) {
4899 Person::players[i]->wentforweapon = 0;
4905 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4914 damage -= multiplier * 13;
4915 permanentdamage -= multiplier * 4;
4916 if (isIdle() || isCrouch()) {
4917 permanentdamage -= multiplier * 4;
4922 if (permanentdamage < 0)
4923 permanentdamage = 0;
4924 if (superpermanentdamage < 0)
4925 superpermanentdamage = 0;
4926 if (permanentdamage < superpermanentdamage) {
4927 permanentdamage = superpermanentdamage;
4929 if (damage < permanentdamage) {
4930 damage = permanentdamage;
4932 if (dead == 1 && damage < damagetolerance) {
4936 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4937 skeleton.joints[i].velocity = 0;
4940 if (permanentdamage > damagetolerance && dead != 2) {
4943 if (weaponactive != -1) {
4944 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4945 weapons[weaponids[0]].velocity.x += .01;
4948 weaponids[0] = weaponids[num_weapons];
4949 if (weaponstuck == num_weapons)
4953 for (unsigned i = 0; i < Person::players.size(); i++) {
4954 Person::players[i]->wentforweapon = 0;
4960 if (!dead && creature == wolftype) {
4961 award_bonus(0, Wolfbonus);
4964 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4965 award_bonus(id, touchofdeath);
4966 if (id != 0 && unconscioustime > .1) {
4974 emit_sound_at(breaksound, coords);
4977 if (skeleton.free == 1) {
4979 pause_sound(whooshsound);
4982 //If knocked over, open hands and close mouth
4983 if (righthandmorphend != 0)
4984 righthandmorphness = 0;
4985 righthandmorphend = 0;
4986 targetrighthandmorphness = 1;
4988 if (lefthandmorphend != 0)
4989 lefthandmorphness = 0;
4990 lefthandmorphend = 0;
4991 targetlefthandmorphness = 1;
4993 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4994 if (headmorphend != 0)
4997 targetheadmorphness = 1;
5001 skeleton.DoGravity(&scale);
5003 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5004 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
5005 award_bonus(id, deepimpact);
5006 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5010 if (!skeleton.joints.empty()) {
5011 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5012 average += skeleton.joints[j].position;
5014 average /= skeleton.joints.size();
5015 coords += average * scale;
5016 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5017 skeleton.joints[j].position -= average;
5019 average /= multiplier;
5023 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5024 velocity += skeleton.joints[i].velocity * scale;
5026 velocity /= skeleton.joints.size();
5028 if (!isnormal(velocity.x) && velocity.x) {
5032 if (findLength(&average) < 10 && dead && skeleton.free) {
5033 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5034 if (skeleton.longdead > 2000) {
5035 if (skeleton.longdead > 6000) {
5037 pause_sound(whooshsound);
5042 if (dead == 2 && bloodloss < damagetolerance) {
5044 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5046 if (bloodtoggle && !bled) {
5047 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5049 if (bloodtoggle && !bled)
5050 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5051 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5052 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5053 float size = .2 * 1.2;
5056 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5060 if (dead == 2 && bloodloss >= damagetolerance) {
5062 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5065 if (bloodtoggle && !bled) {
5066 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5068 if (bloodtoggle && !bled)
5069 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5070 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5071 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5075 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5082 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5083 bool canrecover = 1;
5084 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5085 startpoint = coords;
5088 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5090 if (velocity.y < -30)
5092 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5093 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5094 colviewer = startpoint;
5095 coltarget = endpoint;
5096 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5105 terrainnormal = jointPos(groin) - jointPos(abdomen);
5106 if (joint(groin).locked && joint(abdomen).locked) {
5107 terrainnormal = jointPos(groin) - jointPos(abdomen);
5108 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5110 if (joint(abdomen).locked && joint(neck).locked) {
5111 terrainnormal = jointPos(abdomen) - jointPos(neck);
5112 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5114 if (joint(groin).locked && joint(neck).locked) {
5115 terrainnormal = jointPos(groin) - jointPos(neck);
5116 middle = (jointPos(groin) + jointPos(neck)) / 2;
5118 Normalise(&terrainnormal);
5120 targetyaw = -asin(0 - terrainnormal.x);
5121 targetyaw *= 360 / 6.28;
5122 if (terrainnormal.z < 0)
5123 targetyaw = 180 - targetyaw;
5127 animTarget = flipanim;
5128 crouchtogglekeydown = 1;
5133 animCurrent = tempanim;
5137 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5138 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5139 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5144 if (findLength(&average) < 10 && !dead && skeleton.free) {
5145 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5146 if (skeleton.longdead > (damage + 500) * 1.5) {
5148 pause_sound(whooshsound);
5154 terrainnormal = jointPos(groin) - jointPos(abdomen);
5155 if (joint(groin).locked && joint(abdomen).locked) {
5156 terrainnormal = jointPos(groin) - jointPos(abdomen);
5157 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5159 if (joint(abdomen).locked && joint(neck).locked) {
5160 terrainnormal = jointPos(abdomen) - jointPos(neck);
5161 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5163 if (joint(groin).locked && joint(neck).locked) {
5164 terrainnormal = jointPos(groin) - jointPos(neck);
5165 middle = (jointPos(groin) + jointPos(neck)) / 2;
5167 Normalise(&terrainnormal);
5169 targetyaw = -asin(0 - terrainnormal.x);
5170 targetyaw *= 360 / 6.28;
5171 if (terrainnormal.z < 0)
5172 targetyaw = 180 - targetyaw;
5175 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5178 if (skeleton.forward.y < 0) {
5179 animTarget = getupfrombackanim;
5183 if (skeleton.forward.y > -.3) {
5184 animTarget = getupfromfrontanim;
5192 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5193 animTarget = rollanim;
5194 targetyaw = lookyaw;
5211 if ( !leftkeydown && !rightkeydown)
5218 if (abs(targettilt2) > 50)
5220 animCurrent = tempanim;
5223 tilt2 = targettilt2;
5225 if (middle.y > 0 && animTarget != rollanim)
5226 targetoffset.y = middle.y + 1;
5228 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5229 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5230 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5237 if (num_weapons > 0)
5238 if (weapons[0].getType() == staff)
5240 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5241 if (velocity.y > -30) {
5243 tempvelocity = velocity;
5244 Normalise(&tempvelocity);
5245 targetyaw = -asin(0 - tempvelocity.x);
5246 targetyaw *= 360 / 6.28;
5248 targetyaw = 180 - targetyaw;
5252 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5253 animTarget = rollanim;
5256 animTarget = backhandspringanim;
5262 emit_sound_at(movewhooshsound, coords, 128.);
5264 animCurrent = animTarget;
5265 frameCurrent = frameTarget - 1;
5277 if (skeleton.freefall == 0)
5282 if (aitype != passivetype || skeleton.free == 1)
5283 if (findLengthfast(&velocity) > .1)
5284 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5285 if (Object::objects[i]->type == firetype)
5286 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) {
5288 if (!Object::objects[i]->onfire) {
5289 emit_sound_at(firestartsound, Object::objects[i]->position);
5291 Object::objects[i]->onfire = 1;
5294 if (Object::objects[i]->onfire) {
5299 if (Object::objects[i]->type == bushtype)
5300 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) {
5302 if (!Object::objects[i]->onfire) {
5303 emit_sound_at(firestartsound, Object::objects[i]->position);
5305 Object::objects[i]->onfire = 1;
5309 if (Object::objects[i]->onfire) {
5313 if (Object::objects[i]->messedwith <= 0) {
5317 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5320 addEnvSound(coords, 4 * findLength(&velocity));
5324 if (environment == grassyenvironment)
5325 howmany = findLength(&velocity) * 4;
5326 if (environment == snowyenvironment)
5327 howmany = findLength(&velocity) * 2;
5329 if (environment != desertenvironment)
5330 for (int j = 0; j < howmany; j++) {
5331 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5332 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5333 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5336 pos.x += float(abs(Random() % 100) - 50) / 200;
5337 pos.y += float(abs(Random() % 100) - 50) / 200;
5338 pos.z += float(abs(Random() % 100) - 50) / 200;
5339 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);
5340 Sprite::setLastSpriteSpecial(1);
5342 howmany = findLength(&velocity) * 4;
5344 if (environment == snowyenvironment)
5345 for (int j = 0; j < howmany; j++) {
5346 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5347 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5348 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5351 pos.x += float(abs(Random() % 100) - 50) / 200;
5352 pos.y += float(abs(Random() % 100) - 50) / 200;
5353 pos.z += float(abs(Random() % 100) - 50) / 200;
5354 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5355 Sprite::setLastSpriteSpecial(2);
5358 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5359 Object::objects[i]->roty += velocity.z * multiplier * 6;
5360 Object::objects[i]->messedwith = .5;
5363 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5364 if (Object::objects[i]->pitch == 0)
5367 tempcoord = coords - Object::objects[i]->position;
5368 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5369 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5370 tempcoord += Object::objects[i]->position;
5372 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) {
5373 if (Object::objects[i]->messedwith <= 0) {
5377 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5380 addEnvSound(coords, 4 * findLength(&velocity));
5384 if (environment == grassyenvironment)
5385 howmany = findLength(&velocity) * 4;
5386 if (environment == snowyenvironment)
5387 howmany = findLength(&velocity) * 2;
5389 if (environment != desertenvironment)
5390 for (int j = 0; j < howmany; j++) {
5391 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5392 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5393 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5395 pos += velocity * .1;
5397 pos.x += float(abs(Random() % 100) - 50) / 150;
5398 pos.y += float(abs(Random() % 100) - 50) / 150;
5399 pos.z += float(abs(Random() % 100) - 50) / 150;
5400 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);
5401 Sprite::setLastSpriteSpecial(1);
5403 howmany = findLength(&velocity) * 4;
5405 if (environment == snowyenvironment)
5406 for (int j = 0; j < howmany; j++) {
5407 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5408 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5409 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5411 pos += velocity * .1;
5413 pos.x += float(abs(Random() % 100) - 50) / 150;
5414 pos.y += float(abs(Random() % 100) - 50) / 150;
5415 pos.z += float(abs(Random() % 100) - 50) / 150;
5416 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5417 Sprite::setLastSpriteSpecial(2);
5420 Object::objects[i]->messedwith = .5;
5425 if (!skeleton.free) {
5428 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5431 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5433 if (Tutorial::active && id != 0)
5435 if (play && aitype != playercontrolled) {
5436 int whichsound = -1;
5437 if (speechdelay <= 0) {
5438 unsigned int i = abs(Random() % 4);
5439 if (creature == rabbittype) {
5441 whichsound = rabbitchitter;
5443 whichsound = rabbitchitter2;
5445 if (creature == wolftype) {
5447 whichsound = growlsound;
5449 whichsound = growl2sound;
5454 if (whichsound != -1) {
5455 emit_sound_at(whichsound, coords);
5459 if (animTarget == staggerbackhighanim)
5461 if (animTarget == staggerbackhardanim)
5463 staggerdelay -= multiplier;
5464 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5466 if (velocity.y < -30 && animTarget == jumpdownanim)
5468 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5469 animTarget = getIdle();
5473 weaponmissdelay -= multiplier;
5474 highreversaldelay -= multiplier;
5475 lowreversaldelay -= multiplier;
5476 lastcollide -= multiplier;
5477 skiddelay -= multiplier;
5478 if (!isnormal(velocity.x) && velocity.x) {
5481 if (!isnormal(targettilt) && targettilt) {
5484 if (!isnormal(targettilt2) && targettilt2) {
5487 if (!isnormal(targetyaw) && targetyaw) {
5491 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5492 //open hands and close mouth
5493 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5494 righthandmorphness = 0;
5495 righthandmorphend = 0;
5496 targetrighthandmorphness = 1;
5499 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5500 lefthandmorphness = 0;
5501 lefthandmorphend = 0;
5502 targetlefthandmorphness = 1;
5505 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5508 targetheadmorphness = 1;
5512 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) {
5513 //open hands and mouth
5514 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5515 righthandmorphness = 0;
5516 righthandmorphend = 0;
5517 targetrighthandmorphness = 1;
5520 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5521 lefthandmorphness = 0;
5522 lefthandmorphend = 0;
5523 targetlefthandmorphness = 1;
5526 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5529 targetheadmorphness = 1;
5533 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5534 //close hands and mouth
5535 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5536 righthandmorphness = 0;
5537 righthandmorphend = 1;
5538 targetrighthandmorphness = 1;
5541 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5542 lefthandmorphness = 0;
5543 lefthandmorphend = 1;
5544 targetlefthandmorphness = 1;
5547 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5550 targetheadmorphness = 1;
5554 if (animTarget == spinkickanim ||
5555 animTarget == staffspinhitreversalanim ||
5556 animTarget == staffspinhitreversedanim ||
5557 animTarget == staffhitreversalanim ||
5558 animTarget == staffhitreversedanim ||
5559 animTarget == hurtidleanim ||
5560 animTarget == winduppunchanim ||
5561 animTarget == swordslashreversalanim ||
5562 animTarget == swordslashreversedanim ||
5563 animTarget == knifeslashreversalanim ||
5564 animTarget == knifeslashreversedanim ||
5565 animTarget == knifethrowanim ||
5566 animTarget == knifefollowanim ||
5567 animTarget == knifefollowedanim ||
5568 animTarget == killanim ||
5569 animTarget == dropkickanim ||
5570 animTarget == upunchanim ||
5571 animTarget == knifeslashstartanim ||
5572 animTarget == swordslashanim ||
5573 animTarget == staffhitanim ||
5574 animTarget == staffspinhitanim ||
5575 animTarget == staffgroundsmashanim ||
5576 animTarget == spinkickreversalanim ||
5577 animTarget == sweepreversalanim ||
5578 animTarget == lowkickanim ||
5579 animTarget == sweepreversedanim ||
5580 animTarget == rabbitkickreversalanim ||
5581 animTarget == rabbitkickreversedanim ||
5582 animTarget == jumpreversalanim ||
5583 animTarget == jumpreversedanim) {
5584 //close hands and yell
5585 if (righthandmorphend != 1 &&
5586 righthandmorphness == targetrighthandmorphness) {
5587 righthandmorphness = 0;
5588 righthandmorphend = 1;
5589 targetrighthandmorphness = 1;
5592 if (lefthandmorphend != 1 &&
5593 lefthandmorphness == targetlefthandmorphness) {
5594 lefthandmorphness = 0;
5595 lefthandmorphend = 1;
5596 targetlefthandmorphness = 1;
5599 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5602 targetheadmorphness = 1;
5609 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5610 (victim->aitype != searchtype) && (aitype != passivetype) &&
5611 (aitype != searchtype) && (victim->id < Person::players.size())) {
5612 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5616 if (!dead && animTarget != hurtidleanim)
5617 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5618 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5621 targetheadmorphness = 1;
5625 if (weaponactive != -1) {
5626 if (weapons[weaponids[weaponactive]].getType() != staff) {
5627 righthandmorphstart = 1;
5628 righthandmorphend = 1;
5630 if (weapons[weaponids[weaponactive]].getType() == staff) {
5631 righthandmorphstart = 2;
5632 righthandmorphend = 2;
5634 targetrighthandmorphness = 1;
5637 terrainnormal = terrain.getNormal(coords.x, coords.z);
5639 if (Animation::animations[animTarget].attack != reversal) {
5640 if (!isnormal(coords.x))
5648 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5649 facing = flatfacing;
5650 ReflectVector(&facing, terrainnormal);
5654 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5656 targettilt2 = -facing.y * 20;
5661 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5663 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5664 flatvelocity = velocity;
5666 flatvelspeed = findLength(&flatvelocity);
5667 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5668 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5673 if (targettilt > 25)
5675 if (targettilt < -25)
5679 if (targettilt2 > 45)
5681 if (targettilt2 < -45)
5683 if (abs(tilt2 - targettilt2) < multiplier * 400)
5684 tilt2 = targettilt2;
5685 else if (tilt2 > targettilt2) {
5686 tilt2 -= multiplier * 400;
5687 } else if (tilt2 < targettilt2) {
5688 tilt2 += multiplier * 400;
5690 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5697 if (!isnormal(targettilt) && targettilt) {
5700 if (!isnormal(targettilt2) && targettilt2) {
5705 if (animTarget == rabbittackleanim) {
5706 velocity += facing * multiplier * speed * 700 * scale;
5707 velspeed = findLength(&velocity);
5708 if (velspeed > speed * 65 * scale) {
5709 velocity /= velspeed;
5710 velspeed = speed * 65 * scale;
5711 velocity *= velspeed;
5713 velocity.y += gravity * multiplier * 20;
5714 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5715 velspeed = findLength(&velocity);
5716 velocity = flatfacing * velspeed;
5718 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5719 if (isRun() || animTarget == rabbitkickanim) {
5720 velocity += facing * multiplier * speed * 700 * scale;
5721 velspeed = findLength(&velocity);
5722 if (velspeed > speed * 45 * scale) {
5723 velocity /= velspeed;
5724 velspeed = speed * 45 * scale;
5725 velocity *= velspeed;
5727 velocity.y += gravity * multiplier * 20;
5728 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5729 velspeed = findLength(&velocity);
5730 if (velspeed < speed * 30 * scale)
5731 velspeed = speed * 30 * scale;
5732 velocity = flatfacing * velspeed;
5734 } else if (isRun()) {
5735 velocity += facing * multiplier * speed * 700 * scale;
5736 velspeed = findLength(&velocity);
5737 if (creature == rabbittype) {
5738 if (velspeed > speed * 55 * scale) {
5739 velocity /= velspeed;
5740 velspeed = speed * 55 * scale;
5741 velocity *= velspeed;
5744 if (creature == wolftype) {
5745 if (velspeed > speed * 75 * scale) {
5746 velocity /= velspeed;
5747 velspeed = speed * 75 * scale;
5748 velocity *= velspeed;
5751 velocity.y += gravity * multiplier * 20;
5752 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5753 velspeed = findLength(&velocity);
5754 velocity = flatfacing * velspeed;
5757 if (animTarget == rollanim && targetFrame().label != 6) {
5758 velocity += facing * multiplier * speed * 700 * scale;
5759 velspeed = findLength(&velocity);
5760 if (velspeed > speed * 45 * scale) {
5761 velocity /= velspeed;
5762 velspeed = speed * 45 * scale;
5763 velocity *= velspeed;
5765 velocity.y += gravity * multiplier * 20;
5766 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5767 velspeed = findLength(&velocity);
5768 velocity = flatfacing * velspeed;
5771 if (animTarget == sneakanim || animTarget == walkanim) {
5772 velocity += facing * multiplier * speed * 700 * scale;
5773 velspeed = findLength(&velocity);
5774 if (velspeed > speed * 12 * scale) {
5775 velocity /= velspeed;
5776 velspeed = speed * 12 * scale;
5777 velocity *= velspeed;
5779 velocity.y += gravity * multiplier * 20;
5780 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5781 velspeed = findLength(&velocity);
5782 velocity = flatfacing * velspeed;
5785 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5786 velocity += facing * multiplier * speed * 700 * scale;
5787 velspeed = findLength(&velocity);
5788 if (velspeed > speed * 2 * scale) {
5789 velocity /= velspeed;
5790 velspeed = speed * 2 * scale;
5791 velocity *= velspeed;
5793 velocity.y += gravity * multiplier * 20;
5794 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5795 velspeed = findLength(&velocity);
5796 velocity = flatfacing * velspeed;
5800 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5801 velocity -= facing * multiplier * speed * 700 * scale;
5802 velspeed = findLength(&velocity);
5803 if (velspeed > speed * 2 * scale) {
5804 velocity /= velspeed;
5805 velspeed = speed * 2 * scale;
5806 velocity *= velspeed;
5808 velocity.y += gravity * multiplier * 20;
5809 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5810 velspeed = findLength(&velocity);
5811 velocity = flatfacing * velspeed * -1;
5814 if (animTarget == fightsidestep) {
5815 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5816 velspeed = findLength(&velocity);
5817 if (velspeed > speed * 12 * scale) {
5818 velocity /= velspeed;
5819 velspeed = speed * 12 * scale;
5820 velocity *= velspeed;
5822 velocity.y += gravity * multiplier * 20;
5823 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5824 velspeed = findLength(&velocity);
5825 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5828 if (animTarget == staggerbackhighanim) {
5829 coords -= facing * multiplier * speed * 16 * scale;
5832 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5833 coords -= facing * multiplier * speed * 20 * scale;
5837 if (animTarget == backhandspringanim) {
5838 //coords-=facing*multiplier*50*scale;
5839 velocity += facing * multiplier * speed * 700 * scale * -1;
5840 velspeed = findLength(&velocity);
5841 if (velspeed > speed * 50 * scale) {
5842 velocity /= velspeed;
5843 velspeed = speed * 50 * scale;
5844 velocity *= velspeed;
5846 velocity.y += gravity * multiplier * 20;
5847 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5848 velspeed = findLength(&velocity);
5849 velocity = flatfacing * velspeed * -1;
5851 if (animTarget == dodgebackanim) {
5852 //coords-=facing*multiplier*50*scale;
5853 velocity += facing * multiplier * speed * 700 * scale * -1;
5854 velspeed = findLength(&velocity);
5855 if (velspeed > speed * 60 * scale) {
5856 velocity /= velspeed;
5857 velspeed = speed * 60 * scale;
5858 velocity *= velspeed;
5860 velocity.y += gravity * multiplier * 20;
5861 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5862 velspeed = findLength(&velocity);
5863 velocity = flatfacing * velspeed * -1;
5866 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5867 velspeed = findLength(&velocity);
5871 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5872 velocity.y += gravity * multiplier;
5875 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5876 coords += velocity * multiplier;
5878 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5879 if (isFlip() && targetFrame().label == 7)
5882 if (animTarget == jumpupanim) {
5884 animTarget = getIdle();
5891 pause_sound(whooshsound);
5892 OPENAL_SetVolume(channels[whooshsound], 0);
5895 if (animTarget == jumpdownanim || isFlip()) {
5896 if (isFlip())jumppower = -4;
5897 animTarget = getLanding();
5898 emit_sound_at(landsound, coords, 128.);
5901 addEnvSound(coords);
5906 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5907 coords.y += gravity * multiplier * 2;
5908 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5909 coords.y = terrain.getHeight(coords.x, coords.z);
5914 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)) {
5915 velspeed = findLength(&velocity);
5917 if (velspeed < multiplier * 300 * scale) {
5920 velocity -= velocity / velspeed * multiplier * 300 * scale;
5922 if (velspeed > 5 && (isLanding() || isLandhard())) {
5923 skiddingdelay += multiplier;
5924 if (skiddelay <= 0) {
5925 FootLand(leftfoot, .5);
5926 FootLand(rightfoot, .5);
5935 velspeed = findLength(&velocity);
5937 if (velspeed > 5 && (isLanding() || isLandhard())) {
5938 skiddingdelay += multiplier;
5939 if (skiddelay <= 0) {
5940 FootLand(leftfoot, .5);
5941 FootLand(rightfoot, .5);
5949 if (skiddingdelay < 0)
5950 skiddingdelay += multiplier;
5951 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5953 if (!onterrain || environment == grassyenvironment) {
5954 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5956 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5960 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5961 terrainnormal = victim->coords - coords;
5962 Normalise(&terrainnormal);
5963 targetyaw = -asin(0 - terrainnormal.x);
5964 targetyaw *= 360 / 6.28;
5965 if (terrainnormal.z < 0)
5966 targetyaw = 180 - targetyaw;
5967 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5970 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5971 targetyaw = victim->targetyaw;
5973 if (animTarget == rabbittacklinganim) {
5974 coords = victim->coords;
5977 skeleton.oldfree = skeleton.free;
5981 midterrain.x = terrain.size * terrain.scale / 2;
5982 midterrain.z = terrain.size * terrain.scale / 2;
5983 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5985 tempposit = coords - midterrain;
5987 Normalise(&tempposit);
5988 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5989 coords.x = tempposit.x + midterrain.x;
5990 coords.z = tempposit.z + midterrain.z;
5996 * inverse kinematics helper function
5998 void IKHelper(Person *p, float interp)
6000 XYZ point, change, change2;
6001 float heightleft, heightright;
6003 // TODO: implement localToWorld and worldToLocal
6004 // but keep in mind it won't be the same math if player is ragdolled or something
6005 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6006 // then comb through code for places where to use it
6008 // point = localToWorld(jointPos(leftfoot))
6009 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6010 // adjust height of foot
6011 heightleft = terrain.getHeight(point.x, point.z) + .04;
6012 point.y = heightleft;
6013 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6014 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6015 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6016 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6017 // move ankle along with foot
6018 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6019 // average knee pos between old and new pos
6020 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6022 // do same as above for right leg
6023 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6024 heightright = terrain.getHeight(point.x, point.z) + .04;
6025 point.y = heightright;
6026 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6027 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6028 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6029 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6030 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6032 // fix up skeleton now that we've moved body parts?
6033 p->skeleton.DoConstraints(&p->coords, &p->scale);
6040 int Person::DrawSkeleton()
6042 int oldplayerdetail;
6043 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6044 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6054 glAlphaFunc(GL_GREATER, 0.0001);
6056 float terrainheight;
6060 if (!isnormal(tilt))
6062 if (!isnormal(tilt2))
6064 oldplayerdetail = playerdetail;
6066 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6069 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6072 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6077 if (playerdetail != oldplayerdetail) {
6079 normalsupdatedelay = 0;
6081 static float updatedelaychange;
6082 static float morphness;
6083 static float framemult;
6085 skeleton.FindForwards();
6086 if (howactive == typesittingwall) {
6087 skeleton.specialforward[1] = 0;
6088 skeleton.specialforward[1].z = 1;
6094 static int weaponattachmuscle;
6095 static int weaponrotatemuscle;
6096 static XYZ weaponpoint;
6097 static int start, endthing;
6098 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6099 if (!isSleeping() && !isSitting()) {
6100 // TODO: give these meaningful names
6101 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6102 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6103 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6104 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6106 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6108 if (creature == wolftype)
6112 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6113 IKHelper(this, target);
6114 if (creature == wolftype)
6115 IKHelper(this, target);
6118 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6119 IKHelper(this, 1 - target);
6120 if (creature == wolftype)
6121 IKHelper(this, 1 - target);
6125 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()))
6128 targetheadyaw = -targetyaw;
6129 targetheadpitch = 0;
6130 if (Animation::animations[animTarget].attack == 3)
6131 targetheadyaw += 180;
6133 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6134 skeleton.drawmodel.vertex[i] = 0;
6135 skeleton.drawmodel.vertex[i].y = 999;
6137 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6138 skeleton.drawmodellow.vertex[i] = 0;
6139 skeleton.drawmodellow.vertex[i].y = 999;
6141 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6142 skeleton.drawmodelclothes.vertex[i] = 0;
6143 skeleton.drawmodelclothes.vertex[i].y = 999;
6145 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6146 // convenience renames
6147 const int p1 = skeleton.muscles[i].parent1->label;
6148 const int p2 = skeleton.muscles[i].parent2->label;
6150 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6155 if (p1 == righthand || p2 == righthand) {
6156 morphness = righthandmorphness;
6157 start = righthandmorphstart;
6158 endthing = righthandmorphend;
6160 if (p1 == lefthand || p2 == lefthand) {
6161 morphness = lefthandmorphness;
6162 start = lefthandmorphstart;
6163 endthing = lefthandmorphend;
6165 if (p1 == head || p2 == head) {
6166 morphness = headmorphness;
6167 start = headmorphstart;
6168 endthing = headmorphend;
6170 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6171 morphness = chestmorphness;
6172 start = chestmorphstart;
6173 endthing = chestmorphend;
6175 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6176 morphness = tailmorphness;
6177 start = tailmorphstart;
6178 endthing = tailmorphend;
6181 skeleton.FindRotationMuscle(i, animTarget);
6182 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6183 glMatrixMode(GL_MODELVIEW);
6187 glRotatef(tilt2, 1, 0, 0);
6189 glRotatef(tilt, 0, 0, 1);
6192 glTranslatef(mid.x, mid.y, mid.z);
6194 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6195 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6197 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6198 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6200 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6201 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6203 if (playerdetail || skeleton.free == 3) {
6204 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6205 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6206 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6207 glMatrixMode(GL_MODELVIEW);
6209 if (p1 == abdomen || p2 == abdomen)
6210 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6211 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6212 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6213 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6214 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6215 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6216 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6217 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6218 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6219 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6220 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6221 if (p1 == head || p2 == head)
6222 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6223 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6224 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6225 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6226 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6227 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6228 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6232 if (!playerdetail || skeleton.free == 3) {
6233 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6234 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6235 glMatrixMode(GL_MODELVIEW);
6237 if (p1 == abdomen || p2 == abdomen)
6238 glTranslatef(v0.x * proportionbody.x,
6239 v0.y * proportionbody.y,
6240 v0.z * proportionbody.z);
6241 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6242 glTranslatef(v0.x * proportionarms.x,
6243 v0.y * proportionarms.y,
6244 v0.z * proportionarms.z);
6245 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6246 glTranslatef(v0.x * proportionlegs.x,
6247 v0.y * proportionlegs.y,
6248 v0.z * proportionlegs.z);
6249 if (p1 == head || p2 == head)
6250 glTranslatef(v0.x * proportionhead.x,
6251 v0.y * proportionhead.y,
6252 v0.z * proportionhead.z);
6254 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6255 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6256 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6257 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6263 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6264 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6266 glMatrixMode(GL_MODELVIEW);
6270 glRotatef(tilt2, 1, 0, 0);
6272 glRotatef(tilt, 0, 0, 1);
6273 glTranslatef(mid.x, mid.y, mid.z);
6274 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6275 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6277 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6278 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6280 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6281 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6283 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6284 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6285 glMatrixMode(GL_MODELVIEW);
6287 if (p1 == abdomen || p2 == abdomen)
6288 glTranslatef(v0.x * proportionbody.x,
6289 v0.y * proportionbody.y,
6290 v0.z * proportionbody.z);
6291 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6292 glTranslatef(v0.x * proportionarms.x,
6293 v0.y * proportionarms.y,
6294 v0.z * proportionarms.z);
6295 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6296 glTranslatef(v0.x * proportionlegs.x,
6297 v0.y * proportionlegs.y,
6298 v0.z * proportionlegs.z);
6299 if (p1 == head || p2 == head)
6300 glTranslatef(v0.x * proportionhead.x,
6301 v0.y * proportionhead.y,
6302 v0.z * proportionhead.z);
6303 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6304 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6305 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6306 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6311 updatedelay = 1 + (float)(Random() % 100) / 1000;
6313 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6314 normalsupdatedelay = 1;
6315 if (playerdetail || skeleton.free == 3)
6316 skeleton.drawmodel.CalculateNormals(0);
6317 if (!playerdetail || skeleton.free == 3)
6318 skeleton.drawmodellow.CalculateNormals(0);
6319 if (skeleton.clothes)
6320 skeleton.drawmodelclothes.CalculateNormals(0);
6322 if (playerdetail || skeleton.free == 3)
6323 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6324 if (!playerdetail || skeleton.free == 3)
6325 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6326 if (skeleton.clothes) {
6327 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6332 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6333 if (updatedelaychange > -realmultiplier * 30)
6334 updatedelaychange = -realmultiplier * 30;
6335 if (updatedelaychange > -framemult * 4)
6336 updatedelaychange = -framemult * 4;
6337 if (skeleton.free == 1)
6338 updatedelaychange *= 6;
6340 updatedelaychange *= 8;
6341 updatedelay += updatedelaychange;
6343 glMatrixMode(GL_MODELVIEW);
6345 glTranslatef(coords.x, coords.y - .02, coords.z);
6346 if (!skeleton.free) {
6347 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6348 glRotatef(yaw, 0, 1, 0);
6352 glColor4f(.4, 1, .4, 1);
6353 glDisable(GL_LIGHTING);
6354 glDisable(GL_TEXTURE_2D);
6357 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6358 XYZ &v0 = skeleton.drawmodel.vertex[i];
6359 glVertex3f(v0.x, v0.y, v0.z);
6366 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6367 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6368 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6369 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6370 glVertex3f(v0.x, v0.y, v0.z);
6371 glVertex3f(v1.x, v1.y, v1.z);
6372 glVertex3f(v1.x, v1.y, v1.z);
6373 glVertex3f(v2.x, v2.y, v2.z);
6374 glVertex3f(v2.x, v2.y, v2.z);
6375 glVertex3f(v0.x, v0.y, v0.z);
6382 terrainlight = terrain.getLighting(coords.x, coords.z);
6383 distance = distsq(&viewer, &coords);
6384 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6388 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6389 if (terrainheight < 1)
6391 if (terrainheight > 1.7)
6392 terrainheight = 1.7;
6394 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6395 glDisable(GL_BLEND);
6396 glAlphaFunc(GL_GREATER, 0.0001);
6397 glEnable(GL_TEXTURE_2D);
6399 glDisable(GL_TEXTURE_2D);
6400 glColor4f(.7, .35, 0, .5);
6402 glEnable(GL_LIGHTING);
6405 if (Tutorial::active && id != 0) {
6406 glColor4f(.7, .7, .7, 0.6);
6408 glEnable(GL_LIGHTING);
6410 if (canattack && cananger)
6411 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6412 glDisable(GL_TEXTURE_2D);
6413 glColor4f(1, 0, 0, 0.8);
6415 glMatrixMode(GL_TEXTURE);
6417 glTranslatef(0, -smoketex, 0);
6418 glTranslatef(-smoketex, 0, 0);
6422 if (Tutorial::active && (id != 0))
6423 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6425 skeleton.drawmodel.draw();
6428 if (!playerdetail) {
6429 if (Tutorial::active && (id != 0))
6430 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6432 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6435 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6436 if (Tutorial::active && id != 0) {
6438 glMatrixMode(GL_MODELVIEW);
6439 glEnable(GL_TEXTURE_2D);
6440 glColor4f(.7, .7, .7, 0.6);
6442 glEnable(GL_LIGHTING);
6444 if (canattack && cananger)
6445 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6446 glDisable(GL_TEXTURE_2D);
6447 glColor4f(1, 0, 0, 0.8);
6449 glMatrixMode(GL_TEXTURE);
6451 glTranslatef(0, -smoketex * .6, 0);
6452 glTranslatef(smoketex * .6, 0, 0);
6455 if (Tutorial::active && (id != 0))
6456 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6458 skeleton.drawmodel.draw();
6461 if (!playerdetail) {
6462 if (Tutorial::active && (id != 0))
6463 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6465 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6470 if (Tutorial::active && id != 0) {
6472 glMatrixMode(GL_MODELVIEW);
6473 glEnable(GL_TEXTURE_2D);
6475 if (skeleton.clothes) {
6479 skeleton.drawmodelclothes.draw();
6481 skeleton.drawmodelclothes.drawimmediate();
6487 if (num_weapons > 0) {
6488 for (k = 0; k < num_weapons; k++) {
6489 int i = weaponids[k];
6490 if (weaponactive == k) {
6491 if (weapons[i].getType() != staff) {
6492 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6493 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6494 weaponattachmuscle = j;
6497 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6498 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) {
6499 weaponrotatemuscle = j;
6502 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6503 if (creature == wolftype)
6504 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6506 if (weapons[i].getType() == staff) {
6507 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6508 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6509 weaponattachmuscle = j;
6512 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6513 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) {
6514 weaponrotatemuscle = j;
6517 //weaponpoint=jointPos(rightwrist);
6518 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6519 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6520 XYZ tempnormthing, vec1, vec2;
6521 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6522 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6523 CrossProduct(&vec1, &vec2, &tempnormthing);
6524 Normalise(&tempnormthing);
6525 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6526 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6529 if (weaponactive != k && weaponstuck != k) {
6530 if (weapons[i].getType() == knife)
6531 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6532 if (weapons[i].getType() == sword)
6533 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6534 if (weapons[i].getType() == staff)
6535 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6536 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6537 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) {
6538 weaponrotatemuscle = j;
6542 if (weaponstuck == k) {
6543 if (weaponstuckwhere == 0)
6544 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6546 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6547 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6548 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) {
6549 weaponrotatemuscle = j;
6553 if (skeleton.free) {
6554 weapons[i].position = weaponpoint * scale + coords;
6555 weapons[i].bigrotation = 0;
6556 weapons[i].bigtilt = 0;
6557 weapons[i].bigtilt2 = 0;
6559 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;
6560 weapons[i].bigrotation = yaw;
6561 weapons[i].bigtilt = tilt;
6562 weapons[i].bigtilt2 = tilt2;
6564 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6565 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6566 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6567 if (weaponactive == k) {
6568 if (weapons[i].getType() == knife) {
6569 weapons[i].smallrotation = 180;
6570 weapons[i].smallrotation2 = 0;
6571 if (isCrouch() || wasCrouch()) {
6572 weapons[i].smallrotation2 = 20;
6574 if (animTarget == hurtidleanim) {
6575 weapons[i].smallrotation2 = 50;
6577 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6578 XYZ temppoint1, temppoint2;
6581 temppoint1 = jointPos(righthand);
6582 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6583 distance = findDistance(&temppoint1, &temppoint2);
6584 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6585 weapons[i].rotation2 *= 360 / 6.28;
6588 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6589 weapons[i].rotation1 *= 360 / 6.28;
6590 weapons[i].rotation3 = 0;
6591 weapons[i].smallrotation = -90;
6592 weapons[i].smallrotation2 = 0;
6593 if (temppoint1.x > temppoint2.x)
6594 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6596 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6597 XYZ temppoint1, temppoint2;
6600 temppoint1 = jointPos(righthand);
6601 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6602 distance = findDistance(&temppoint1, &temppoint2);
6603 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6604 weapons[i].rotation2 *= 360 / 6.28;
6607 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6608 weapons[i].rotation1 *= 360 / 6.28;
6609 weapons[i].rotation3 = 0;
6610 weapons[i].smallrotation = 90;
6611 weapons[i].smallrotation2 = 0;
6612 if (temppoint1.x > temppoint2.x)
6613 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6615 if (animTarget == knifethrowanim) {
6616 weapons[i].smallrotation = 90;
6617 //weapons[i].smallrotation2=-90;
6618 weapons[i].smallrotation2 = 0;
6619 weapons[i].rotation1 = 0;
6620 weapons[i].rotation2 = 0;
6621 weapons[i].rotation3 = 0;
6623 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6624 weapons[i].smallrotation = -90;
6625 weapons[i].rotation1 = 0;
6626 weapons[i].rotation2 = 0;
6627 weapons[i].rotation3 = 0;
6630 if (weapons[i].getType() == sword) {
6631 weapons[i].smallrotation = 0;
6632 weapons[i].smallrotation2 = 0;
6633 if (animTarget == knifethrowanim) {
6634 weapons[i].smallrotation = -90;
6635 weapons[i].smallrotation2 = 0;
6636 weapons[i].rotation1 = 0;
6637 weapons[i].rotation2 = 0;
6638 weapons[i].rotation3 = 0;
6640 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)) {
6641 XYZ temppoint1, temppoint2;
6644 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6645 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6646 distance = findDistance(&temppoint1, &temppoint2);
6647 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6648 weapons[i].rotation2 *= 360 / 6.28;
6651 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6652 weapons[i].rotation1 *= 360 / 6.28;
6653 weapons[i].rotation3 = 0;
6654 weapons[i].smallrotation = 90;
6655 weapons[i].smallrotation2 = 0;
6656 if (temppoint1.x > temppoint2.x)
6657 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6660 if (weapons[i].getType() == staff) {
6661 weapons[i].smallrotation = 100;
6662 weapons[i].smallrotation2 = 0;
6663 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6664 XYZ temppoint1, temppoint2;
6667 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6668 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6669 distance = findDistance(&temppoint1, &temppoint2);
6670 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6671 weapons[i].rotation2 *= 360 / 6.28;
6674 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6675 weapons[i].rotation1 *= 360 / 6.28;
6676 weapons[i].rotation3 = 0;
6677 weapons[i].smallrotation = 90;
6678 weapons[i].smallrotation2 = 0;
6679 if (temppoint1.x > temppoint2.x)
6680 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6684 if (weaponactive != k && weaponstuck != k) {
6685 if (weapons[i].getType() == knife) {
6686 weapons[i].smallrotation = -70;
6687 weapons[i].smallrotation2 = 10;
6689 if (weapons[i].getType() == sword) {
6690 weapons[i].smallrotation = -100;
6691 weapons[i].smallrotation2 = -8;
6693 if (weapons[i].getType() == staff) {
6694 weapons[i].smallrotation = -100;
6695 weapons[i].smallrotation2 = -8;
6698 if (weaponstuck == k) {
6699 if (weaponstuckwhere == 0)
6700 weapons[i].smallrotation = 180;
6702 weapons[i].smallrotation = 0;
6703 weapons[i].smallrotation2 = 10;
6712 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6714 if (animCurrent != animTarget)
6716 if (skeleton.free == 2)
6725 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6727 static float distance;
6728 static float olddistance;
6729 static int intersecting;
6730 static int firstintersecting;
6733 static XYZ start, end;
6734 static float slopethreshold = -.4;
6736 firstintersecting = -1;
6740 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6743 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6744 for (int i = 0; i < 4; i++) {
6745 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
6746 if (model->Triangles[j].facenormal.y <= slopethreshold) {
6748 distance = abs((model->Triangles[j].facenormal.x * p1->x) + (model->Triangles[j].facenormal.y * p1->y) + (model->Triangles[j].facenormal.z * p1->z) - ((model->Triangles[j].facenormal.x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->Triangles[j].facenormal.y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->Triangles[j].facenormal.z * model->vertex[model->Triangles[j].vertex[0]].z)));
6749 if (distance < radius) {
6750 point = *p1 - model->Triangles[j].facenormal * distance;
6751 if (PointInTriangle( &point, model->Triangles[j].facenormal, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))
6754 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6755 &model->vertex[model->Triangles[j].vertex[1]],
6758 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6759 &model->vertex[model->Triangles[j].vertex[2]],
6762 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6763 &model->vertex[model->Triangles[j].vertex[2]],
6766 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
6770 if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->Triangles[j].facenormal, &point)) {
6771 p1->y = point.y + radius;
6772 if ((animTarget == jumpdownanim || isFlip())) {
6773 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6776 if (animTarget == jumpupanim) {
6778 animTarget = getIdle();
6785 pause_sound(whooshsound);
6786 OPENAL_SetVolume(channels[whooshsound], 0);
6789 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6792 animTarget = getLanding();
6793 emit_sound_at(landsound, coords, 128.);
6796 addEnvSound(coords);
6803 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6804 olddistance = distance;
6805 firstintersecting = j;
6810 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
6811 if (model->Triangles[j].facenormal.y > slopethreshold) {
6814 start.y -= radius / 4;
6815 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6816 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6817 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6818 distance = abs((model->Triangles[j].facenormal.x * start.x)
6819 + (model->Triangles[j].facenormal.y * start.y)
6820 + (model->Triangles[j].facenormal.z * start.z)
6821 - ((model->Triangles[j].facenormal.x * v0.x)
6822 + (model->Triangles[j].facenormal.y * v0.y)
6823 + (model->Triangles[j].facenormal.z * v0.z)));
6824 if (distance < radius * .5) {
6825 point = start - model->Triangles[j].facenormal * distance;
6826 if (PointInTriangle( &point, model->Triangles[j].facenormal, &v0, &v1, &v2))
6829 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6831 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6833 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6835 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
6836 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6838 velocity -= DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6839 if (findLengthfast(&start) < findLengthfast(&velocity))
6842 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
6845 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6846 olddistance = distance;
6847 firstintersecting = j;
6854 *p = DoRotation(*p, 0, *rotate, 0);
6857 *p1 = DoRotation(*p1, 0, *rotate, 0);
6859 return firstintersecting;
6862 int findPathDist(int start, int end)
6867 unsigned int smallestcount = 1000;
6868 for (char i = 0; i < 50; i++) {
6869 unsigned int count = 0;
6874 while (last != end && count < 30) {
6876 for (int j = 0; j < Game::numpathpoints; j++) {
6877 if (j != last && j != last2 && j != last3 && j != last4) {
6879 if (Game::numpathpointconnect[j])
6880 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6881 if (Game::pathpointconnect[j][k] == last)connected = 1;
6884 if (Game::numpathpointconnect[last])
6885 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
6886 if (Game::pathpointconnect[last][k] == j)connected = 1;
6889 if (closest == -1 || Random() % 2 == 0) {
6900 if (count < smallestcount) {
6901 smallestcount = count;
6904 return smallestcount;
6907 void Person::takeWeapon(int weaponId)
6910 weapons[weaponId].owner = id;
6911 if (num_weapons > 0) {
6912 weaponids[num_weapons] = weaponids[0];
6915 weaponids[0] = weaponId;
6918 void Person::addClothes()
6920 if (numclothes > 0) {
6921 for (int i = 0; i < numclothes; i++) {
6928 bool Person::addClothes(const int& clothesId)
6931 const std::string fileName = clothes[clothesId];
6933 GLubyte* array = &skeleton.skinText[0];
6937 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6942 float tintr = clothestintr[clothesId];
6943 float tintg = clothestintg[clothesId];
6944 float tintb = clothestintb[clothesId];
6946 if (tintr > 1) tintr = 1;
6947 if (tintg > 1) tintg = 1;
6948 if (tintb > 1) tintb = 1;
6950 if (tintr < 0) tintr = 0;
6951 if (tintg < 0) tintg = 0;
6952 if (tintb < 0) tintb = 0;
6954 int bytesPerPixel = texture.bpp / 8;
6958 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6959 if (bytesPerPixel == 3)
6961 else if ((i + 1) % 4 == 0)
6962 alphanum = texture.data[i];
6963 if ((i + 1) % 4 || bytesPerPixel == 3) {
6965 texture.data[i] *= tintr;
6967 texture.data[i] *= tintg;
6969 texture.data[i] *= tintb;
6970 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6982 if (aitype != playercontrolled && !Dialog::inDialog()) {
6984 //disable movement in editor
6985 if (Game::editorenabled)
6989 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
6990 Person::players[0]->coords.y > coords.y + 2 &&
6991 !Person::players[0]->onterrain)
6995 if (aitype == pathfindtype) {
6996 if (finalpathfindpoint == -1) {
6997 float closestdistance;
7002 closestdistance = -1;
7003 for (int j = 0; j < Game::numpathpoints; j++) {
7004 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7005 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7007 finaltarget = Game::pathpoint[j];
7010 finalpathfindpoint = closest;
7011 for (int j = 0; j < Game::numpathpoints; j++) {
7012 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7013 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7014 if (sq(tempdist) < closestdistance)
7015 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7016 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7017 closestdistance = sq(tempdist);
7019 finaltarget = colpoint;
7023 finalpathfindpoint = closest;
7026 if (targetpathfindpoint == -1) {
7027 float closestdistance;
7032 closestdistance = -1;
7033 if (lastpathfindpoint == -1) {
7034 for (int j = 0; j < Game::numpathpoints; j++) {
7035 if (j != lastpathfindpoint)
7036 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7037 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7041 targetpathfindpoint = closest;
7042 for (int j = 0; j < Game::numpathpoints; j++)
7043 if (j != lastpathfindpoint)
7044 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7045 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint );
7046 if (sq(tempdist) < closestdistance) {
7047 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7048 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7049 closestdistance = sq(tempdist);
7054 targetpathfindpoint = closest;
7056 for (int j = 0; j < Game::numpathpoints; j++)
7057 if (j != lastpathfindpoint &&
7058 j != lastpathfindpoint2 &&
7059 j != lastpathfindpoint3 &&
7060 j != lastpathfindpoint4) {
7062 if (Game::numpathpointconnect[j])
7063 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7064 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7067 if (Game::numpathpointconnect[lastpathfindpoint])
7068 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7069 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7072 tempdist = findPathDist(j, finalpathfindpoint);
7073 if (closest == -1 || tempdist < closestdistance) {
7074 closestdistance = tempdist;
7079 targetpathfindpoint = closest;
7082 losupdatedelay -= multiplier;
7084 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7085 lookyaw = targetyaw;
7087 //reached target point
7088 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7089 lastpathfindpoint4 = lastpathfindpoint3;
7090 lastpathfindpoint3 = lastpathfindpoint2;
7091 lastpathfindpoint2 = lastpathfindpoint;
7092 lastpathfindpoint = targetpathfindpoint;
7093 if (lastpathfindpoint2 == -1)
7094 lastpathfindpoint2 = lastpathfindpoint;
7095 if (lastpathfindpoint3 == -1)
7096 lastpathfindpoint3 = lastpathfindpoint2;
7097 if (lastpathfindpoint4 == -1)
7098 lastpathfindpoint4 = lastpathfindpoint3;
7099 targetpathfindpoint = -1;
7101 if ( distsqflat(&coords, &finalfinaltarget) <
7102 distsqflat(&coords, &finaltarget) ||
7103 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7104 lastpathfindpoint == finalpathfindpoint) {
7105 aitype = passivetype;
7116 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7117 targetyaw += 90 * (whichdirection * 2 - 1);
7119 if (collided < 1 || animTarget != jumpupanim)
7121 if ((collided > .8 && jumppower >= 5))
7124 if ((!Tutorial::active || cananger) &&
7126 !Person::players[0]->dead &&
7127 distsq(&coords, &Person::players[0]->coords) < 400 &&
7129 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7130 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7131 !Game::editorenabled &&
7132 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7133 aitype = attacktypecutoff;
7134 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7135 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7136 !Game::editorenabled)
7137 aitype = attacktypecutoff;
7139 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7140 losupdatedelay = .2;
7141 for (unsigned j = 0; j < Person::players.size(); j++)
7142 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7143 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7144 if (distsq(&coords, &Person::players[j]->coords) < 400)
7145 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7146 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7147 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
7148 DoRotation(jointPos(head), 0, yaw, 0)
7150 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
7151 *Person::players[j]->scale + Person::players[j]->coords) ||
7152 (Person::players[j]->animTarget == hanganim &&
7153 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7154 aitype = searchtype;
7156 lastseen = Person::players[j]->coords;
7161 if (aitype == attacktypecutoff && Game::musictype != 2)
7162 if (creature != wolftype) {
7168 if (aitype != passivetype && Game::leveltime > .5)
7169 howactive = typeactive;
7171 if (aitype == passivetype) {
7172 aiupdatedelay -= multiplier;
7173 losupdatedelay -= multiplier;
7174 lastseentime += multiplier;
7175 pausetime -= multiplier;
7176 if (lastseentime > 1)
7179 if (aiupdatedelay < 0) {
7180 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7181 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7182 lookyaw = targetyaw;
7183 aiupdatedelay = .05;
7185 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7186 if (waypointtype[waypoint] == wppause)
7189 if (waypoint > numwaypoints - 1)
7195 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7206 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7207 if (!avoidsomething)
7208 targetyaw += 90 * (whichdirection * 2 - 1);
7210 XYZ leftpos, rightpos;
7211 float leftdist, rightdist;
7212 leftpos = coords + DoRotation(facing, 0, 90, 0);
7213 rightpos = coords - DoRotation(facing, 0, 90, 0);
7214 leftdist = distsq(&leftpos, &avoidwhere);
7215 rightdist = distsq(&rightpos, &avoidwhere);
7216 if (leftdist < rightdist)
7223 if (collided < 1 || animTarget != jumpupanim)
7225 if ((collided > .8 && jumppower >= 5))
7230 if (!Game::editorenabled) {
7231 if (howactive <= typesleeping)
7232 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7233 for (int j = 0; j < numenvsounds; j++) {
7234 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7235 if (vol > 0 && distsq(&coords, &envsound[j]) <
7236 2 * (vol + vol * (creature == rabbittype) * 3))
7237 aitype = attacktypecutoff;
7240 if (aitype != passivetype) {
7241 if (howactive == typesleeping)
7242 setTargetAnimation(getupfromfrontanim);
7243 howactive = typeactive;
7247 if (howactive < typesleeping &&
7248 ((!Tutorial::active || cananger) && hostile) &&
7249 !Person::players[0]->dead &&
7250 distsq(&coords, &Person::players[0]->coords) < 400 &&
7252 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7253 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7254 aitype = attacktypecutoff;
7255 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7256 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7257 aitype = attacktypecutoff;
7260 if (creature == wolftype) {
7262 for (unsigned j = 0; j < Person::players.size(); j++) {
7263 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7264 float smelldistance = 50;
7265 if (j == 0 && Person::players[j]->num_weapons > 0) {
7266 if (weapons[Person::players[j]->weaponids[0]].bloody)
7267 smelldistance = 100;
7268 if (Person::players[j]->num_weapons == 2)
7269 if (weapons[Person::players[j]->weaponids[1]].bloody)
7270 smelldistance = 100;
7273 smelldistance = 100;
7274 windsmell = windvector;
7275 Normalise(&windsmell);
7276 windsmell = windsmell * 2 + Person::players[j]->coords;
7277 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7278 aitype = attacktypecutoff;
7283 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7284 losupdatedelay = .2;
7285 for (unsigned j = 0; j < Person::players.size(); j++) {
7286 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7287 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7288 if (distsq(&coords, &Person::players[j]->coords) < 400)
7289 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7290 if ((-1 == Object::checkcollide(
7291 DoRotation(jointPos(head), 0, yaw, 0)*
7293 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
7294 Person::players[j]->scale + Person::players[j]->coords) &&
7295 !Person::players[j]->isWallJump()) ||
7296 (Person::players[j]->animTarget == hanganim &&
7297 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7299 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7304 if (lastseentime <= 0) {
7305 aitype = searchtype;
7307 lastseen = Person::players[j]->coords;
7315 if (aitype == attacktypecutoff && Game::musictype != 2) {
7316 if (creature != wolftype) {
7320 if (creature == wolftype) {
7330 if (aitype == searchtype) {
7331 aiupdatedelay -= multiplier;
7332 losupdatedelay -= multiplier;
7334 lastseentime -= multiplier;
7335 lastchecktime -= multiplier;
7337 if (isRun() && !onground) {
7338 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7339 XYZ test2 = coords + facing;
7341 XYZ test = coords + facing;
7343 j = Object::checkcollide(test2, test, laststanding);
7345 j = Object::checkcollide(test2, test);
7348 setTargetAnimation(getStop());
7351 //aitype=passivetype;
7352 aitype = pathfindtype;
7353 finalfinaltarget = waypoints[waypoint];
7354 finalpathfindpoint = -1;
7355 targetpathfindpoint = -1;
7356 lastpathfindpoint = -1;
7357 lastpathfindpoint2 = -1;
7358 lastpathfindpoint3 = -1;
7359 lastpathfindpoint4 = -1;
7364 //check out last seen location
7365 if (aiupdatedelay < 0) {
7366 targetyaw = roughDirectionTo(coords, lastseen);
7367 lookyaw = targetyaw;
7368 aiupdatedelay = .05;
7371 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7374 lastseen.x += (float(Random() % 100) - 50) / 25;
7375 lastseen.z += (float(Random() % 100) - 50) / 25;
7386 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7387 if (!avoidsomething)
7388 targetyaw += 90 * (whichdirection * 2 - 1);
7390 XYZ leftpos, rightpos;
7391 float leftdist, rightdist;
7392 leftpos = coords + DoRotation(facing, 0, 90, 0);
7393 rightpos = coords - DoRotation(facing, 0, 90, 0);
7394 leftdist = distsq(&leftpos, &avoidwhere);
7395 rightdist = distsq(&rightpos, &avoidwhere);
7396 if (leftdist < rightdist)
7403 if (collided < 1 || animTarget != jumpupanim)
7405 if ((collided > .8 && jumppower >= 5))
7408 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7409 for (int k = 0; k < numenvsounds; k++) {
7410 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7411 aitype = attacktypecutoff;
7415 if (!Person::players[0]->dead &&
7416 losupdatedelay < 0 &&
7417 !Game::editorenabled &&
7419 ((!Tutorial::active || cananger) && hostile)) {
7420 losupdatedelay = .2;
7421 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7422 aitype = attacktypecutoff;
7425 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7426 //TODO: factor out canSeePlayer()
7427 if (distsq(&coords, &Person::players[0]->coords) < 400)
7428 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7429 if ((Object::checkcollide(
7430 DoRotation(jointPos(head), 0, yaw, 0)*
7432 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
7433 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
7434 (Person::players[0]->animTarget == hanganim && normaldotproduct(
7435 Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7436 /* //TODO: changed j to 0 on a whim, make sure this is correct
7437 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7438 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7440 aitype = attacktypecutoff;
7445 if (lastseentime < 0) {
7446 //aitype=passivetype;
7448 aitype = pathfindtype;
7449 finalfinaltarget = waypoints[waypoint];
7450 finalpathfindpoint = -1;
7451 targetpathfindpoint = -1;
7452 lastpathfindpoint = -1;
7453 lastpathfindpoint2 = -1;
7454 lastpathfindpoint3 = -1;
7455 lastpathfindpoint4 = -1;
7459 if (aitype != gethelptype)
7462 //get help from buddies
7463 if (aitype == gethelptype) {
7464 runninghowlong += multiplier;
7465 aiupdatedelay -= multiplier;
7467 if (aiupdatedelay < 0 || ally == 0) {
7471 //TODO: factor out closest search somehow
7474 float closestdist = -1;
7475 for (unsigned k = 0; k < Person::players.size(); k++) {
7476 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7477 (Person::players[k]->howactive < typedead1) &&
7478 !Person::players[k]->skeleton.free &&
7479 (Person::players[k]->aitype == passivetype)) {
7480 float distance = distsq(&coords, &Person::players[k]->coords);
7481 if (closestdist == -1 || distance < closestdist) {
7482 closestdist = distance;
7488 if (closest != -1) {
7493 lastseen = Person::players[0]->coords;
7500 XYZ facing = coords;
7501 XYZ flatfacing = Person::players[ally]->coords;
7502 facing.y += jointPos(head).y * scale;
7503 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7504 if (-1 != Object::checkcollide(facing, flatfacing))
7507 //no available ally, run back to player
7509 Person::players[ally]->skeleton.free ||
7510 Person::players[ally]->aitype != passivetype ||
7511 lastseentime <= 0) {
7512 aitype = searchtype;
7518 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7519 lookyaw = targetyaw;
7520 aiupdatedelay = .05;
7523 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7524 aitype = searchtype;
7526 Person::players[ally]->aitype = searchtype;
7527 if (Person::players[ally]->lastseentime < lastseentime) {
7528 Person::players[ally]->lastseen = lastseen;
7529 Person::players[ally]->lastseentime = lastseentime;
7530 Person::players[ally]->lastchecktime = lastchecktime;
7534 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7535 if (!avoidsomething)
7536 targetyaw += 90 * (whichdirection * 2 - 1);
7538 XYZ leftpos, rightpos;
7539 float leftdist, rightdist;
7540 leftpos = coords + DoRotation(facing, 0, 90, 0);
7541 rightpos = coords - DoRotation(facing, 0, 90, 0);
7542 leftdist = distsq(&leftpos, &avoidwhere);
7543 rightdist = distsq(&rightpos, &avoidwhere);
7544 if (leftdist < rightdist)
7558 if (collided < 1 || animTarget != jumpupanim)
7560 if (collided > .8 && jumppower >= 5)
7564 //retreiving a weapon on the ground
7565 if (aitype == getweapontype) {
7566 aiupdatedelay -= multiplier;
7567 lastchecktime -= multiplier;
7569 if (aiupdatedelay < 0) {
7575 float closestdist = -1;
7576 for (unsigned k = 0; k < weapons.size(); k++)
7577 if (weapons[k].owner == -1) {
7578 float distance = distsq(&coords, &weapons[k].position);
7579 if (closestdist == -1 || distance < closestdist) {
7580 closestdist = distance;
7593 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7594 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7595 aitype = attacktypecutoff;
7598 if (!Person::players[0]->dead)
7600 if (weapons[ally].owner != -1 ||
7601 distsq(&coords, &weapons[ally].position) > 16) {
7602 aitype = attacktypecutoff;
7605 //TODO: factor these out as moveToward()
7606 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7607 lookyaw = targetyaw;
7608 aiupdatedelay = .05;
7612 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7613 if (!avoidsomething)
7614 targetyaw += 90 * (whichdirection * 2 - 1);
7616 XYZ leftpos, rightpos;
7617 float leftdist, rightdist;
7618 leftpos = coords + DoRotation(facing, 0, 90, 0);
7619 rightpos = coords - DoRotation(facing, 0, 90, 0);
7620 leftdist = distsq(&leftpos, &avoidwhere);
7621 rightdist = distsq(&rightpos, &avoidwhere);
7622 if (leftdist < rightdist)
7636 if (animTarget != crouchremoveknifeanim &&
7637 animTarget != removeknifeanim)
7638 throwtogglekeydown = 0;
7641 if (collided < 1 || animTarget != jumpupanim)
7643 if ((collided > .8 && jumppower >= 5))
7647 if (aitype == attacktypecutoff) {
7648 aiupdatedelay -= multiplier;
7649 //dodge or reverse rabbit kicks, knife throws, flips
7650 if (damage < damagetolerance * 2 / 3)
7651 if ((Person::players[0]->animTarget == rabbitkickanim ||
7652 Person::players[0]->animTarget == knifethrowanim ||
7653 (Person::players[0]->isFlip() &&
7654 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7655 !Person::players[0]->skeleton.free &&
7656 (aiupdatedelay < .1)) {
7660 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7661 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7662 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7663 if (abs(Random() % 2) == 0) {
7664 setTargetAnimation(backhandspringanim);
7666 setTargetAnimation(rollanim);
7668 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7671 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
7672 setTargetAnimation(flipanim);
7677 aiupdatedelay = .02;
7679 //get confused by flips
7680 if (Person::players[0]->isFlip() &&
7681 !Person::players[0]->skeleton.free &&
7682 Person::players[0]->animTarget != walljumprightkickanim &&
7683 Person::players[0]->animTarget != walljumpleftkickanim) {
7684 if (distsq(&Person::players[0]->coords, &coords) < 25)
7685 if ((1 - damage / damagetolerance) > .5)
7688 //go for weapon on the ground
7689 if (wentforweapon < 3)
7690 for (unsigned k = 0; k < weapons.size(); k++)
7691 if (creature != wolftype)
7692 if (num_weapons == 0 &&
7693 weapons[k].owner == -1 &&
7694 weapons[k].velocity.x == 0 &&
7695 weapons[k].velocity.z == 0 &&
7696 weapons[k].velocity.y == 0) {
7697 if (distsq(&coords, &weapons[k].position) < 16) {
7700 aitype = getweapontype;
7704 //dodge/reverse walljump kicks
7705 if (damage < damagetolerance / 2)
7706 if (Animation::animations[animTarget].height != highheight)
7707 if (damage < damagetolerance * .5 &&
7708 ((Person::players[0]->animTarget == walljumprightkickanim ||
7709 Person::players[0]->animTarget == walljumpleftkickanim) &&
7710 ((aiupdatedelay < .15 &&
7712 (aiupdatedelay < .08 &&
7713 difficulty != 2)))) {
7716 //walked off a ledge (?)
7717 if (isRun() && !onground)
7718 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7719 XYZ test2 = coords + facing;
7721 XYZ test = coords + facing;
7723 j = Object::checkcollide(test2, test, laststanding);
7725 j = Object::checkcollide(test2, test);
7728 setTargetAnimation(getStop());
7731 aitype = pathfindtype;
7732 finalfinaltarget = waypoints[waypoint];
7733 finalpathfindpoint = -1;
7734 targetpathfindpoint = -1;
7735 lastpathfindpoint = -1;
7736 lastpathfindpoint2 = -1;
7737 lastpathfindpoint3 = -1;
7738 lastpathfindpoint4 = -1;
7742 //lose sight of player in the air (?)
7743 if (Person::players[0]->coords.y > coords.y + 5 &&
7744 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7745 !Person::players[0]->onterrain) {
7746 aitype = pathfindtype;
7747 finalfinaltarget = waypoints[waypoint];
7748 finalpathfindpoint = -1;
7749 targetpathfindpoint = -1;
7750 lastpathfindpoint = -1;
7751 lastpathfindpoint2 = -1;
7752 lastpathfindpoint3 = -1;
7753 lastpathfindpoint4 = -1;
7755 //it's time to think (?)
7756 if (aiupdatedelay < 0 &&
7757 !Animation::animations[animTarget].attack &&
7758 animTarget != staggerbackhighanim &&
7759 animTarget != staggerbackhardanim &&
7760 animTarget != backhandspringanim &&
7761 animTarget != dodgebackanim) {
7763 if (weaponactive == -1 && num_weapons > 0)
7764 drawkeydown = Random() % 2;
7767 rabbitkickenabled = Random() % 2;
7769 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7770 XYZ targetpoint = Person::players[0]->coords;
7771 if (distsq(&Person::players[0]->coords, &coords) <
7772 distsq(&rotatetarget, &coords))
7773 targetpoint += Person::players[0]->velocity *
7774 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7775 targetyaw = roughDirectionTo(coords, targetpoint);
7776 lookyaw = targetyaw;
7777 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7779 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7781 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7782 distsq(&coords, &Person::players[0]->coords) < 9) &&
7783 Person::players[0]->weaponactive != -1)
7785 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7789 //chill out around the corpse
7790 if (Person::players[0]->dead) {
7792 if (Random() % 10 == 0)
7794 if (Random() % 100 == 0) {
7795 aitype = pathfindtype;
7796 finalfinaltarget = waypoints[waypoint];
7797 finalpathfindpoint = -1;
7798 targetpathfindpoint = -1;
7799 lastpathfindpoint = -1;
7800 lastpathfindpoint2 = -1;
7801 lastpathfindpoint3 = -1;
7802 lastpathfindpoint4 = -1;
7811 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7812 targetyaw += 90 * (whichdirection * 2 - 1);
7814 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7818 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7822 if (aitype != playercontrolled &&
7827 for (unsigned j = 0; j < Person::players.size(); j++)
7828 if (j != id && !Person::players[j]->skeleton.free &&
7829 Person::players[j]->hasvictim &&
7830 (Tutorial::active && reversaltrain ||
7831 Random() % 2 == 0 && difficulty == 2 ||
7832 Random() % 4 == 0 && difficulty == 1 ||
7833 Random() % 8 == 0 && difficulty == 0 ||
7834 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7835 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7836 (Random() % 2 == 0 || difficulty == 2) ||
7837 (isIdle() || isRun()) &&
7838 Person::players[j]->weaponactive != -1 ||
7839 Person::players[j]->animTarget == swordslashanim &&
7840 weaponactive != -1 ||
7841 Person::players[j]->animTarget == staffhitanim ||
7842 Person::players[j]->animTarget == staffspinhitanim))
7843 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7844 Person::players[j]->victim == Person::players[id] &&
7845 (Person::players[j]->animTarget == sweepanim ||
7846 Person::players[j]->animTarget == spinkickanim ||
7847 Person::players[j]->animTarget == staffhitanim ||
7848 Person::players[j]->animTarget == staffspinhitanim ||
7849 Person::players[j]->animTarget == winduppunchanim ||
7850 Person::players[j]->animTarget == upunchanim ||
7851 Person::players[j]->animTarget == wolfslapanim ||
7852 Person::players[j]->animTarget == knifeslashstartanim ||
7853 Person::players[j]->animTarget == swordslashanim &&
7854 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7855 weaponactive != -1))) {
7863 Person::players[target]->Reverse();
7868 if (collided > .8 && jumppower >= 5 ||
7869 distsq(&coords, &Person::players[0]->coords) > 400 &&
7871 creature == rabbittype)
7873 //TODO: why are we controlling the human?
7874 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7875 Person::players[0]->jumpkeydown = 0;
7876 if (Person::players[0]->animTarget == jumpdownanim &&
7877 distsq(&Person::players[0]->coords, &coords) < 40)
7882 if (Tutorial::active)
7887 XYZ facing = coords;
7888 XYZ flatfacing = Person::players[0]->coords;
7889 facing.y += jointPos(head).y * scale;
7890 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7892 if (-1 != Object::checkcollide(facing, flatfacing)) {
7895 if (lastseentime <= 0 &&
7896 (creature != wolftype ||
7897 weaponstuck == -1)) {
7898 aitype = searchtype;
7900 lastseen = Person::players[0]->coords;
7907 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7908 (aitype == attacktypecutoff ||
7909 aitype == searchtype))
7910 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7911 XYZ test = Person::players[0]->coords;
7913 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7917 if (aitype == passivetype && !(numwaypoints > 1) ||
7919 pause && damage > superpermanentdamage) {
7938 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7939 facing = flatfacing;
7941 if (aitype == attacktypecutoff) {
7942 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7943 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7944 } else if (howactive >= typesleeping) {
7945 targetheadyaw = targetyaw;
7946 targetheadpitch = 0;
7948 if (interestdelay <= 0) {
7949 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
7950 headtarget = coords;
7951 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
7952 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
7953 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
7954 headtarget += facing * 1.5;
7956 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
7957 targetheadpitch = pitchTo(coords, headtarget);