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 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation/Animation.h"
29 #include "Utils/Folders.h"
31 extern float multiplier;
32 extern Terrain terrain;
34 extern int environment;
36 extern FRUSTUM frustum;
38 extern float realmultiplier;
40 extern float slomodelay;
41 extern bool cellophane;
42 extern float texdetail;
43 extern float realtexdetail;
44 extern GLubyte bloodText[512 * 512 * 3];
45 extern GLubyte wolfbloodText[512 * 512 * 3];
46 extern int bloodtoggle;
47 extern Objects objects;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern int tutoriallevel;
61 extern float smoketex;
62 extern int tutorialstage;
63 extern bool reversaltrain;
64 extern bool canattack;
66 extern float damagedealt;
68 extern float hostiletime;
70 extern bool gamestarted;
72 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
77 animCurrent(bounceidleanim),
78 animTarget(bounceidleanim),
85 howactive(typeactive),
87 superruntoggle(false),
88 lastattack(0), lastattack2(0), lastattack3(0),
89 currentoffset(), targetoffset(), offset(),
121 rabbitkickenabled(false),
130 damagetolerance(200),
133 superpermanentdamage(0),
147 bleedx(0), bleedy(0),
151 headyaw(0), headpitch(0),
152 targetheadyaw(0), targetheadpitch(0),
163 normalsupdatedelay(0),
166 forwardkeydown(false),
167 forwardstogglekeydown(false),
172 jumptogglekeydown(false),
173 crouchkeydown(false),
174 crouchtogglekeydown(false),
176 drawtogglekeydown(false),
178 throwtogglekeydown(false),
179 attackkeydown(false),
184 crouchkeydowntime(0),
198 whichdirection(false),
199 whichdirectiondelay(0),
200 avoidsomething(false),
209 lefthandmorphness(0),
210 righthandmorphness(0),
214 targetlefthandmorphness(0),
215 targetrighthandmorphness(0),
216 targetheadmorphness(1),
217 targetchestmorphness(0),
218 targettailmorphness(0),
219 lefthandmorphstart(0), lefthandmorphend(0),
220 righthandmorphstart(0), righthandmorphend(0),
221 headmorphstart(0), headmorphend(0),
222 chestmorphstart(0), chestmorphend(0),
223 tailmorphstart(0), tailmorphend(0),
226 highreversaldelay(0),
229 creature(rabbittype),
276 finalpathfindpoint(0),
277 targetpathfindpoint(0),
278 lastpathfindpoint(0),
279 lastpathfindpoint2(0),
280 lastpathfindpoint3(0),
281 lastpathfindpoint4(0),
298 neckspurtparticledelay(0),
302 rabbitkickragdoll(false),
310 /* Read a person in tfile. Throws an error if it’s not valid */
311 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
314 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
316 funpackf(tfile, "Bi", &howactive);
318 howactive = typeactive;
321 funpackf(tfile, "Bf", &scale);
326 funpackf(tfile, "Bb", &immobile);
331 funpackf(tfile, "Bf", &yaw);
336 if (num_weapons < 0 || num_weapons > 5) {
337 throw InvalidPersonException();
339 if (num_weapons > 0 && num_weapons < 5) {
340 for (int j = 0; j < num_weapons; j++) {
341 weaponids[j] = weapons.size();
343 funpackf(tfile, "Bi", &type);
344 weapons.push_back(Weapon(type, id));
347 funpackf(tfile, "Bi", &numwaypoints);
348 for (int j = 0; j < numwaypoints; j++) {
349 funpackf(tfile, "Bf", &waypoints[j].x);
350 funpackf(tfile, "Bf", &waypoints[j].y);
351 funpackf(tfile, "Bf", &waypoints[j].z);
353 funpackf(tfile, "Bi", &waypointtype[j]);
355 waypointtype[j] = wpkeepwalking;
359 funpackf(tfile, "Bi", &waypoint);
360 if (waypoint > (numwaypoints - 1)) {
364 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
365 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
366 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
367 funpackf(tfile, "Bf Bf", &power, &speedmult);
369 float headprop, legprop, armprop, bodyprop;
372 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
380 if (creature == wolftype) {
381 proportionhead = 1.1 * headprop;
382 proportionbody = 1.1 * bodyprop;
383 proportionarms = 1.1 * armprop;
384 proportionlegs = 1.1 * legprop;
385 } else if (creature == rabbittype) {
386 proportionhead = 1.2 * headprop;
387 proportionbody = 1.05 * bodyprop;
388 proportionarms = 1.00 * armprop;
389 proportionlegs = 1.1 * legprop;
390 proportionlegs.y = 1.05 * legprop;
393 funpackf(tfile, "Bi", &numclothes);
394 for (int k = 0; k < numclothes; k++) {
396 funpackf(tfile, "Bi", &templength);
397 for (int l = 0; l < templength; l++)
398 funpackf(tfile, "Bb", &clothes[k][l]);
399 clothes[k][templength] = '\0';
400 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
406 if (creature == wolftype) {
408 damagetolerance = 300;
415 realoldcoords = coords;
418 void Person::skeletonLoad(bool clothes)
421 if (creature != wolftype) {
423 "Skeleton/BasicFigure",
424 "Skeleton/BasicFigureLow",
425 "Skeleton/RabbitBelt",
427 "Models/Body2.solid",
428 "Models/Body3.solid",
429 "Models/Body4.solid",
430 "Models/Body5.solid",
431 "Models/Body6.solid",
432 "Models/Body7.solid",
433 "Models/BodyLow.solid",
439 "Skeleton/BasicFigureWolf",
440 "Skeleton/BasicFigureWolfLow",
441 "Skeleton/RabbitBelt",
443 "Models/Wolf2.solid",
444 "Models/Wolf3.solid",
445 "Models/Wolf4.solid",
446 "Models/Wolf5.solid",
447 "Models/Wolf6.solid",
448 "Models/Wolf7.solid",
449 "Models/WolfLow.solid",
455 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
461 * GameTick/doPlayerCollisions
463 void Person::CheckKick()
466 && (animTarget == rabbitkickanim
468 && victim != this->shared_from_this()
470 && animCurrent == rabbitkickanim)
471 && distsq(&coords, &victim->coords) < 1.2
472 && !victim->skeleton.free))
475 if (Animation::animations[victim->animTarget].height != lowheight) {
476 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
477 XYZ relative = velocity;
479 Normalise(&relative);
483 if (tutoriallevel != 1)
484 emit_sound_at(heavyimpactsound, victim->coords);
486 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
487 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
490 victim->DoDamage(100 * damagemult / victim->protectionhigh);
496 animTarget = backflipanim;
498 velocity = facing * -10;
502 resume_stream(whooshsound);
504 award_bonus(id, cannon);
505 } else if (victim->isCrouch()) {
506 animTarget = rabbitkickreversedanim;
507 animCurrent = rabbitkickreversedanim;
508 victim->animCurrent = rabbitkickreversalanim;
509 victim->animTarget = rabbitkickreversalanim;
515 victim->oldcoords = victim->coords;
516 coords = victim->coords;
517 victim->targetyaw = targetyaw;
518 victim->victim = this->shared_from_this();
525 * GameTick/doPlayerCollisions - spread fire between players
526 * GameTick/doDevKeys - press f to ignite
527 * Person::DoStuff - spread fire from lit campfires and bushes
529 void Person::CatchFire()
531 XYZ flatfacing, flatvelocity;
533 for (int i = 0; i < 10; i++) {
534 howmany = abs(Random() % (skeleton.joints.size()));
536 flatvelocity = skeleton.joints[howmany].velocity;
537 flatfacing = skeleton.joints[howmany].position * scale + coords;
539 flatvelocity = velocity;
540 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
542 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
547 emit_sound_at(firestartsound, coords);
549 emit_stream_at(stream_firesound, coords);
557 * idle animation for this creature (depending on status)
559 int Person::getIdle()
561 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
563 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
564 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
565 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
566 victim->id < Person::players.size())) {
567 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
568 if (creature == rabbittype)
569 return fightidleanim;
570 if (creature == wolftype)
573 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
574 if (weapons[weaponids[weaponactive]].getType() == knife)
575 return knifefightidleanim;
576 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
577 return swordfightidlebothanim;
578 if (weapons[weaponids[weaponactive]].getType() == sword)
579 return swordfightidleanim;
580 if (weapons[weaponids[weaponactive]].getType() == staff)
581 return swordfightidleanim;
583 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
584 return fightsidestep;
586 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
588 if (howactive == typesitting) return sitanim;
589 if (howactive == typesittingwall) return sitwallanim;
590 if (howactive == typesleeping) return sleepanim;
591 if (howactive == typedead1) return dead1anim;
592 if (howactive == typedead2) return dead2anim;
593 if (howactive == typedead3) return dead3anim;
594 if (howactive == typedead4) return dead4anim;
595 if (creature == rabbittype) return bounceidleanim;
596 if (creature == wolftype) return wolfidle;
601 * crouch animation for this creature
603 int Person::getCrouch()
605 if (creature == rabbittype)
607 if (creature == wolftype)
608 return wolfcrouchanim;
613 * running animation for this creature (can be upright or all fours)
617 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
619 if (creature == wolftype && (!superruntoggle))
622 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
623 return rabbitrunninganim;
624 if (creature == wolftype && (superruntoggle))
625 return wolfrunninganim;
631 int Person::getStop()
633 if (creature == rabbittype)
635 if (creature == wolftype)
642 int Person::getLanding()
644 if (creature == rabbittype)
646 if (creature == wolftype)
653 int Person::getLandhard()
655 if (creature == rabbittype)
657 if (creature == wolftype)
658 return wolflandhardanim;
665 * Person::DoAnimations
668 SolidHitBonus(int playerid)
670 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
671 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
673 award_bonus(playerid, solidhit);
677 * spawns blood effects
679 void Person::DoBlood(float howmuch, int which)
681 // FIXME: should abstract out inputs
682 static int bleedxint, bleedyint;
684 if (bloodtoggle && tutoriallevel != 1) {
685 if (bleeding <= 0 && spurt) {
687 for (int i = 0; i < 3; i++) {
688 // emit blood particles
691 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
692 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
693 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
694 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
697 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
698 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
699 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
700 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
703 if (Random() % 2 == 0) // 50% chance
704 for (int i = 0; i < 3; i++) {
705 if (Random() % 2 != 0) {
706 // emit teeth particles
709 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
710 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
713 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
714 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
718 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
720 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
722 Sprite::setLastSpriteSpecial(3); // sets it to teeth
727 // FIXME: manipulating attributes
728 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
731 if (creature == rabbittype)
732 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) {
733 bleedxint = abs(Random() % 512);
734 bleedyint = abs(Random() % 512);
736 if (creature == wolftype)
737 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) {
738 bleedxint = abs(Random() % 512);
739 bleedyint = abs(Random() % 512);
743 bleedy /= realtexdetail;
744 bleedx /= realtexdetail;
745 direction = abs(Random() % 2) * 2 - 1;
754 * spawns big blood effects and ???
755 * modifies character's skin texture
757 void Person::DoBloodBig(float howmuch, int which)
759 static int bleedxint, bleedyint, i, j;
761 if (howmuch && id == 0)
764 if (tutoriallevel != 1 || id == 0)
765 if (aitype != playercontrolled && howmuch > 0) {
769 if (creature == wolftype) {
770 int i = abs(Random() % 2);
772 whichsound = snarlsound;
774 whichsound = snarl2sound;
776 if (creature == rabbittype) {
777 int i = abs(Random() % 2);
779 whichsound = rabbitpainsound;
780 if (i == 1 && howmuch >= 2)
781 whichsound = rabbitpain1sound;
784 if (whichsound != -1) {
785 emit_sound_at(whichsound, coords);
790 if (id == 0 && howmuch > 0) {
794 if (bloodtoggle && decals && tutoriallevel != 1) {
795 if (bleeding <= 0 && spurt) {
797 for (int i = 0; i < 3; i++) {
798 // emit blood particles
799 // FIXME: copypaste from above
802 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
803 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
804 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
805 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
808 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
809 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
810 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
811 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
816 // weird texture manipulation code follows.
817 // looks like this is painting blood onto the character's skin texture
818 // FIXME: surely there's a better way
820 int offsetx = 0, offsety = 0;
822 offsety = Random() % 40;
823 offsetx = abs(Random() % 60);
825 if (which == 190 || which == 185) {
826 offsety = Random() % 40;
827 offsetx = abs(Random() % 100) - 20;
830 offsety = Random() % 10;
831 offsetx = Random() % 10;
834 offsety = Random() % 20;
835 offsetx = Random() % 20;
837 if (which == 220 || which == 215) {
847 if (creature == rabbittype)
848 for (i = 0; i < 512; i++) {
849 for (j = 0; j < 512; j++) {
850 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
851 if (i < startx) startx = i;
852 if (j < starty) starty = j;
853 if (i > endx) endx = i;
854 if (j > endy) endy = j;
858 if (creature == wolftype)
859 for (i = 0; i < 512; i++) {
860 for (j = 0; j < 512; j++) {
861 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
862 if (i < startx) startx = i;
863 if (j < starty) starty = j;
864 if (i > endx) endx = i;
865 if (j > endy) endy = j;
875 if (startx < 0) startx = 0;
876 if (starty < 0) starty = 0;
877 if (endx > 512 - 1) endx = 512 - 1;
878 if (endy > 512 - 1) endy = 512 - 1;
879 if (endx < startx) endx = startx;
880 if (endy < starty) endy = starty;
882 startx /= realtexdetail;
883 starty /= realtexdetail;
884 endx /= realtexdetail;
885 endy /= realtexdetail;
887 int texdetailint = realtexdetail;
889 if (creature == rabbittype)
890 for (i = startx; i < endx; i++) {
891 for (j = starty; j < endy; j++) {
892 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) {
893 color = Random() % 85 + 170;
894 where = i * skeleton.skinsize * 3 + j * 3;
895 if (skeleton.skinText[where + 0] > color / 2)
896 skeleton.skinText[where + 0] = color / 2;
897 skeleton.skinText[where + 1] = 0;
898 skeleton.skinText[where + 2] = 0;
902 if (creature == wolftype)
903 for (i = startx; i < endx; i++) {
904 for (j = starty; j < endy; j++) {
905 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) {
906 color = Random() % 85 + 170;
907 where = i * skeleton.skinsize * 3 + j * 3;
908 if (skeleton.skinText[where + 0] > color / 2)
909 skeleton.skinText[where + 0] = color / 2;
910 skeleton.skinText[where + 1] = 0;
911 skeleton.skinText[where + 2] = 0;
915 skeleton.drawmodel.textureptr.bind();
920 if (creature == rabbittype)
921 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) {
922 bleedxint = abs(Random() % 512);
923 bleedyint = abs(Random() % 512);
925 if (creature == wolftype)
926 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) {
927 bleedxint = abs(Random() % 512);
928 bleedyint = abs(Random() % 512);
930 bleedy = bleedxint + offsetx;
931 bleedx = bleedyint + offsety;
932 bleedy /= realtexdetail;
933 bleedx /= realtexdetail;
938 if (bleedx > skeleton.skinsize - 1)
939 bleedx = skeleton.skinsize - 1;
940 if (bleedy > skeleton.skinsize - 1)
941 bleedy = skeleton.skinsize - 1;
942 direction = abs(Random() % 2) * 2 - 1;
945 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
946 deathbleeding += bleeding;
947 bloodloss += bleeding * 3;
949 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
950 if (abs(Random() % 2) == 0) {
951 aitype = gethelptype;
954 aitype = attacktypecutoff;
962 * similar to DoBloodBig
964 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
968 static XYZ startpoint, endpoint, colpoint, movepoint;
969 static float rotationpoint;
971 static XYZ p1, p2, p3, p0;
974 float coordsx, coordsy;
977 if (bloodtoggle && decals && tutoriallevel != 1) {
980 where = DoRotation(where, 0, -yaw, 0);
988 // ray testing for a tri in the character model
989 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
990 if (whichtri != -1) {
991 // low level geometry math
993 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
994 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
995 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
997 bary.x = distsq(&p0, &p1);
998 bary.y = distsq(&p0, &p2);
999 bary.z = distsq(&p0, &p3);
1001 total = bary.x + bary.y + bary.z;
1006 bary.x = 1 - bary.x;
1007 bary.y = 1 - bary.y;
1008 bary.z = 1 - bary.z;
1010 total = bary.x + bary.y + bary.z;
1016 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1017 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1018 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1019 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1020 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1021 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1022 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;
1023 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;
1025 if (bleeding <= 0 && spurt) {
1027 for (int i = 0; i < 3; i++) {
1028 // emit blood particles
1029 // FIXME: more copypaste code
1031 if (skeleton.free) {
1032 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1033 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1034 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1035 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1038 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1039 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1040 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1041 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1046 // texture manipulation follows
1048 int offsetx = 0, offsety = 0;
1049 offsetx = (1 + coordsy) * 512 - 291;
1050 offsety = coordsx * 512 - 437;
1057 if (creature == rabbittype)
1058 for (i = 0; i < 512; i++) {
1059 for (j = 0; j < 512; j++) {
1060 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1061 if (i < startx) startx = i;
1062 if (j < starty) starty = j;
1063 if (i > endx) endx = i;
1064 if (j > endy) endy = j;
1068 if (creature == wolftype)
1069 for (i = 0; i < 512; i++) {
1070 for (j = 0; j < 512; j++) {
1071 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1072 if (i < startx) startx = i;
1073 if (j < starty) starty = j;
1074 if (i > endx) endx = i;
1075 if (j > endy) endy = j;
1084 if (startx < 0) startx = 0;
1085 if (starty < 0) starty = 0;
1086 if (endx > 512 - 1) endx = 512 - 1;
1087 if (endy > 512 - 1) endy = 512 - 1;
1088 if (endx < startx) endx = startx;
1089 if (endy < starty) endy = starty;
1091 startx /= realtexdetail;
1092 starty /= realtexdetail;
1093 endx /= realtexdetail;
1094 endy /= realtexdetail;
1096 int texdetailint = realtexdetail;
1098 if (creature == rabbittype)
1099 for (i = startx; i < endx; i++) {
1100 for (j = starty; j < endy; j++) {
1101 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) {
1102 color = Random() % 85 + 170;
1103 where = i * skeleton.skinsize * 3 + j * 3;
1104 if (skeleton.skinText[where + 0] > color / 2)
1105 skeleton.skinText[where + 0] = color / 2;
1106 skeleton.skinText[where + 1] = 0;
1107 skeleton.skinText[where + 2] = 0;
1108 } 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) {
1109 color = Random() % 85 + 170;
1110 where = i * skeleton.skinsize * 3 + j * 3;
1111 if (skeleton.skinText[where + 0] > color / 2)
1112 skeleton.skinText[where + 0] = color / 2;
1113 skeleton.skinText[where + 1] = 0;
1114 skeleton.skinText[where + 2] = 0;
1118 if (creature == wolftype)
1119 for (i = startx; i < endx; i++) {
1120 for (j = starty; j < endy; j++) {
1121 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) {
1122 color = Random() % 85 + 170;
1123 where = i * skeleton.skinsize * 3 + j * 3;
1124 if (skeleton.skinText[where + 0] > color / 2)
1125 skeleton.skinText[where + 0] = color / 2;
1126 skeleton.skinText[where + 1] = 0;
1127 skeleton.skinText[where + 2] = 0;
1128 } 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) {
1129 color = Random() % 85 + 170;
1130 where = i * skeleton.skinsize * 3 + j * 3;
1131 if (skeleton.skinText[where + 0] > color / 2)
1132 skeleton.skinText[where + 0] = color / 2;
1133 skeleton.skinText[where + 1] = 0;
1134 skeleton.skinText[where + 2] = 0;
1138 skeleton.drawmodel.textureptr.bind();
1141 bleedy = (1 + coordsy) * 512;
1142 bleedx = coordsx * 512;
1143 bleedy /= realtexdetail;
1144 bleedx /= realtexdetail;
1149 if (bleedx > skeleton.skinsize - 1)
1150 bleedx = skeleton.skinsize - 1;
1151 if (bleedy > skeleton.skinsize - 1)
1152 bleedy = skeleton.skinsize - 1;
1153 direction = abs(Random() % 2) * 2 - 1;
1158 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1159 deathbleeding += bleeding;
1160 bloodloss += bleeding * 3;
1162 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1163 if (abs(Random() % 2) == 0) {
1164 aitype = gethelptype;
1167 aitype = attacktypecutoff;
1178 * guessing this performs a reversal
1180 void Person::Reverse()
1182 if (!((victim->aitype == playercontrolled
1184 || staggerdelay <= 0)
1185 && victim->animTarget != jumpupanim
1186 && victim->animTarget != jumpdownanim
1187 && (tutoriallevel != 1 || cananger)
1191 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1192 && (victim->id != 0 || difficulty >= 2)
1193 && (creature != wolftype || victim->creature == wolftype))
1196 if (animTarget == sweepanim) {
1197 animTarget = sweepreversedanim;
1198 animCurrent = sweepreversedanim;
1199 victim->animCurrent = sweepreversalanim;
1200 victim->animTarget = sweepreversalanim;
1202 if (animTarget == spinkickanim) {
1203 animTarget = spinkickreversedanim;
1204 animCurrent = spinkickreversedanim;
1205 victim->animCurrent = spinkickreversalanim;
1206 victim->animTarget = spinkickreversalanim;
1208 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1209 if (animTarget == rabbittacklinganim) {
1212 victim->frameCurrent = 6;
1213 victim->frameTarget = 7;
1215 animTarget = upunchreversedanim;
1216 animCurrent = upunchreversedanim;
1217 victim->animCurrent = upunchreversalanim;
1218 victim->animTarget = upunchreversalanim;
1220 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1221 if (victim->weaponactive != -1) {
1222 victim->throwtogglekeydown = 1;
1223 XYZ tempVelocity = victim->velocity * .2;
1224 if (tempVelocity.x == 0)
1225 tempVelocity.x = .1;
1226 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1227 victim->num_weapons--;
1228 if (victim->num_weapons) {
1229 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1230 if (victim->weaponstuck == victim->num_weapons)
1231 victim->weaponstuck = 0;
1234 victim->weaponactive = -1;
1235 for (unsigned j = 0; j < Person::players.size(); j++) {
1236 Person::players[j]->wentforweapon = 0;
1240 animTarget = staffhitreversedanim;
1241 animCurrent = staffhitreversedanim;
1242 victim->animCurrent = staffhitreversalanim;
1243 victim->animTarget = staffhitreversalanim;
1245 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1246 if (victim->weaponactive != -1) {
1247 victim->throwtogglekeydown = 1;
1248 XYZ tempVelocity = victim->velocity * .2;
1249 if (tempVelocity.x == 0)
1250 tempVelocity.x = .1;
1251 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1252 victim->num_weapons--;
1253 if (victim->num_weapons) {
1254 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1255 if (victim->weaponstuck == victim->num_weapons)
1256 victim->weaponstuck = 0;
1259 victim->weaponactive = -1;
1260 for (unsigned j = 0; j < Person::players.size(); j++) {
1261 Person::players[j]->wentforweapon = 0;
1264 animTarget = staffspinhitreversedanim;
1265 animCurrent = staffspinhitreversedanim;
1266 victim->animCurrent = staffspinhitreversalanim;
1267 victim->animTarget = staffspinhitreversalanim;
1269 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1270 if (victim->weaponactive != -1) {
1271 victim->throwtogglekeydown = 1;
1272 XYZ tempVelocity = victim->velocity * .2;
1273 if (tempVelocity.x == 0)
1274 tempVelocity.x = .1;
1275 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1276 victim->num_weapons--;
1277 if (victim->num_weapons) {
1278 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1279 if (victim->weaponstuck == victim->num_weapons)
1280 victim->weaponstuck = 0;
1283 victim->weaponactive = -1;
1284 for (unsigned j = 0; j < Person::players.size(); j++) {
1285 Person::players[j]->wentforweapon = 0;
1288 animTarget = swordslashreversedanim;
1289 animCurrent = swordslashreversedanim;
1290 victim->animCurrent = swordslashreversalanim;
1291 victim->animTarget = swordslashreversalanim;
1293 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1294 if (victim->weaponactive != -1) {
1295 victim->throwtogglekeydown = 1;
1296 XYZ tempVelocity = victim->velocity * .2;
1297 if (tempVelocity.x == 0)
1298 tempVelocity.x = .1;
1299 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1300 victim->num_weapons--;
1301 if (victim->num_weapons) {
1302 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1303 if (victim->weaponstuck == victim->num_weapons)
1304 victim->weaponstuck = 0;
1307 victim->weaponactive = -1;
1308 for (unsigned j = 0; j < Person::players.size(); j++) {
1309 Person::players[j]->wentforweapon = 0;
1312 animTarget = knifeslashreversedanim;
1313 animCurrent = knifeslashreversedanim;
1314 victim->animCurrent = knifeslashreversalanim;
1315 victim->animTarget = knifeslashreversalanim;
1317 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1318 victim->targettilt2 = targettilt2;
1319 victim->frameCurrent = frameCurrent;
1320 victim->frameTarget = frameTarget;
1321 victim->target = target;
1322 victim->velocity = 0;
1323 victim->oldcoords = victim->coords;
1324 victim->coords = coords;
1325 victim->targetyaw = targetyaw;
1326 victim->yaw = targetyaw;
1327 victim->victim = this->shared_from_this();
1329 if (animTarget == winduppunchanim) {
1330 animTarget = winduppunchblockedanim;
1331 victim->animTarget = blockhighleftanim;
1332 victim->frameTarget = 1;
1333 victim->target = .5;
1334 victim->victim = this->shared_from_this();
1335 victim->targetyaw = targetyaw + 180;
1337 if (animTarget == wolfslapanim) {
1338 animTarget = winduppunchblockedanim;
1339 victim->animTarget = blockhighleftanim;
1340 victim->frameTarget = 1;
1341 victim->target = .5;
1342 victim->victim = this->shared_from_this();
1343 victim->targetyaw = targetyaw + 180;
1345 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1346 animTarget = swordslashparriedanim;
1347 parriedrecently = .4;
1348 victim->parriedrecently = 0;
1349 victim->animTarget = swordslashparryanim;
1350 victim->frameTarget = 1;
1351 victim->target = .5;
1352 victim->victim = this->shared_from_this();
1353 victim->targetyaw = targetyaw + 180;
1355 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1356 if (victim->weaponactive != -1) {
1357 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1358 if (weapons[victim->weaponids[0]].getType() == staff)
1359 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1360 if (weapons[weaponids[0]].getType() == staff)
1361 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1362 emit_sound_at(swordstaffsound, victim->coords);
1364 emit_sound_at(metalhitsound, victim->coords);
1368 victim->Puff(righthand);
1370 victim->frameTarget = 0;
1371 victim->animTarget = staggerbackhighanim;
1372 victim->targetyaw = targetyaw + 180;
1374 aim = DoRotation(facing, 0, 90, 0) * 21;
1376 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1377 victim->num_weapons--;
1378 if (victim->num_weapons) {
1379 victim->weaponids[0] = victim->weaponids[num_weapons];
1380 if (victim->weaponstuck == victim->num_weapons)
1381 victim->weaponstuck = 0;
1383 victim->weaponactive = -1;
1384 for (unsigned i = 0; i < Person::players.size(); i++) {
1385 Person::players[i]->wentforweapon = 0;
1389 if (abs(Random() % 20) == 0) {
1390 if (weaponactive != -1) {
1391 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1392 if (weapons[victim->weaponids[0]].getType() == staff)
1393 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1394 if (weapons[weaponids[0]].getType() == staff)
1395 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1397 emit_sound_at(swordstaffsound, coords);
1399 emit_sound_at(metalhitsound, coords);
1407 animTarget = staggerbackhighanim;
1408 targetyaw = targetyaw + 180;
1410 aim = DoRotation(facing, 0, 90, 0) * 21;
1412 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1415 weaponids[0] = weaponids[num_weapons];
1416 if (weaponstuck == num_weapons)
1420 for (unsigned i = 0; i < Person::players.size(); i++) {
1421 Person::players[i]->wentforweapon = 0;
1428 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1429 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1430 victim->animTarget = dodgebackanim;
1431 victim->frameTarget = 0;
1435 rotatetarget = coords - victim->coords;
1436 Normalise(&rotatetarget);
1437 victim->targetyaw = -asin(0 - rotatetarget.x);
1438 victim->targetyaw *= 360 / 6.28;
1439 if (rotatetarget.z < 0)
1440 victim->targetyaw = 180 - victim->targetyaw;
1442 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1444 victim->lastattack3 = victim->lastattack2;
1445 victim->lastattack2 = victim->lastattack;
1446 victim->lastattack = victim->animTarget;
1448 victim->animTarget = sweepanim;
1449 victim->frameTarget = 0;
1453 rotatetarget = coords - victim->coords;
1454 Normalise(&rotatetarget);
1455 victim->targetyaw = -asin(0 - rotatetarget.x);
1456 victim->targetyaw *= 360 / 6.28;
1457 if (rotatetarget.z < 0)
1458 victim->targetyaw = 180 - victim->targetyaw;
1460 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1462 victim->lastattack3 = victim->lastattack2;
1463 victim->lastattack2 = victim->lastattack;
1464 victim->lastattack = victim->animTarget;
1469 victim->velocity = 0;
1471 if (aitype != playercontrolled)
1473 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1475 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1477 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1480 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1487 void Person::DoDamage(float howmuch)
1489 // subtract health (temporary?)
1490 if (tutoriallevel != 1)
1491 damage += howmuch / power;
1494 damagedealt += howmuch / power;
1496 damagetaken += howmuch / power;
1499 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1502 if (tutoriallevel != 1)
1503 permanentdamage += howmuch / 2 / power;
1504 if (tutoriallevel != 1)
1505 superpermanentdamage += howmuch / 4 / power;
1507 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1509 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1513 camerashake += howmuch / 100;
1514 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1515 blackout = damage / damagetolerance;
1520 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1521 aitype = attacktypecutoff;
1522 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1523 if (abs(Random() % 2) == 0) {
1524 aitype = gethelptype;
1527 aitype = attacktypecutoff;
1531 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1534 for (int i = 0; i < skeleton.joints.size(); i++) {
1535 if (skeleton.free) {
1536 flatvelocity2 = skeleton.joints[i].velocity;
1537 flatfacing2 = skeleton.joints[i].position * scale + coords;
1539 flatvelocity2 = velocity;
1540 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1542 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1543 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1544 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1545 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1546 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1547 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1550 emit_sound_at(splattersound, coords);
1555 if (!dead && creature == wolftype) {
1556 award_bonus(0, Wolfbonus);
1563 if (tutoriallevel != 1 || id == 0)
1564 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1565 int whichsound = -1;
1567 if (creature == wolftype) {
1568 int i = abs(Random() % 2);
1570 whichsound = snarlsound;
1572 whichsound = snarl2sound;
1574 if (creature == rabbittype) {
1575 int i = abs(Random() % 2);
1577 whichsound = rabbitpainsound;
1578 if (i == 1 && damage > damagetolerance)
1579 whichsound = rabbitpain1sound;
1582 if (whichsound != -1) {
1583 emit_sound_at(whichsound, coords);
1584 addEnvSound(coords);
1591 * calculate/animate head facing direction?
1593 void Person::DoHead()
1595 static XYZ rotatearound;
1597 static float lookspeed = 500;
1599 if (!freeze && !winfreeze) {
1602 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1603 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1605 while (targetheadyaw > 180)targetheadyaw -= 360;
1606 while (targetheadyaw < -180)targetheadyaw += 360;
1608 if (targetheadyaw > 160)
1609 targetheadpitch = targetheadpitch * -1;
1610 if (targetheadyaw < -160)
1611 targetheadpitch = targetheadpitch * -1;
1612 if (targetheadyaw > 160)
1613 targetheadyaw = targetheadyaw - 180;
1614 if (targetheadyaw < -160)
1615 targetheadyaw = targetheadyaw + 180;
1617 if (targetheadpitch > 120)
1618 targetheadpitch = 120;
1619 if (targetheadpitch < -120)
1620 targetheadpitch = -120;
1621 if (targetheadyaw > 120)
1622 targetheadyaw = 120;
1623 if (targetheadyaw < -120)
1624 targetheadyaw = -120;
1627 targetheadpitch = 0;
1629 if (targetheadyaw > 80)
1631 if (targetheadyaw < -80)
1632 targetheadyaw = -80;
1633 if (targetheadpitch > 50)
1634 targetheadpitch = 50;
1635 if (targetheadpitch < -50)
1636 targetheadpitch = -50;
1639 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1640 headyaw = targetheadyaw;
1641 else if (headyaw > targetheadyaw) {
1642 headyaw -= multiplier * lookspeed;
1643 } else if (headyaw < targetheadyaw) {
1644 headyaw += multiplier * lookspeed;
1647 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1648 headpitch = targetheadpitch;
1649 else if (headpitch > targetheadpitch) {
1650 headpitch -= multiplier * lookspeed / 2;
1651 } else if (headpitch < targetheadpitch) {
1652 headpitch += multiplier * lookspeed / 2;
1655 rotatearound = jointPos(neck);
1656 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1660 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1661 facing = DoRotation(facing, headpitch * .4, 0, 0);
1662 facing = DoRotation(facing, 0, headyaw * .4, 0);
1665 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1666 facing = DoRotation(facing, headpitch * .8, 0, 0);
1667 facing = DoRotation(facing, 0, headyaw * .8, 0);
1670 if (animTarget == walkanim) {
1671 facing = DoRotation(facing, headpitch * .6, 0, 0);
1672 facing = DoRotation(facing, 0, headyaw * .6, 0);
1675 skeleton.specialforward[0] = facing;
1676 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1677 for (int i = 0; i < skeleton.muscles.size(); i++) {
1678 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1679 skeleton.FindRotationMuscle(i, animTarget);
1686 * ragdolls character?
1688 void Person::RagDoll(bool checkcollision)
1693 if (!skeleton.free) {
1696 if (id == 0 && isFlip())
1703 facing = DoRotation(facing, 0, yaw, 0);
1705 skeleton.freetime = 0;
1707 skeleton.longdead = 0;
1710 skeleton.broken = 0;
1711 skeleton.spinny = 1;
1713 skeleton.freefall = 1;
1715 if (!isnormal(velocity.x)) velocity.x = 0;
1716 if (!isnormal(velocity.y)) velocity.y = 0;
1717 if (!isnormal(velocity.z)) velocity.z = 0;
1718 if (!isnormal(yaw)) yaw = 0;
1719 if (!isnormal(coords.x)) coords = 0;
1720 if (!isnormal(tilt)) tilt = 0;
1721 if (!isnormal(tilt2)) tilt2 = 0;
1723 for (int i = 0; i < skeleton.joints.size(); i++) {
1724 skeleton.joints[i].delay = 0;
1725 skeleton.joints[i].locked = 0;
1726 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1727 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1728 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1729 skeleton.joints[i].position.y += .1;
1730 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1731 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1734 for (int i = 0; i < skeleton.joints.size(); i++) {
1735 skeleton.joints[i].velocity = 0;
1736 skeleton.joints[i].velchange = 0;
1738 skeleton.DoConstraints(&coords, &scale);
1739 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1740 skeleton.DoConstraints(&coords, &scale);
1741 skeleton.DoConstraints(&coords, &scale);
1742 skeleton.DoConstraints(&coords, &scale);
1743 skeleton.DoConstraints(&coords, &scale);
1746 speed = targetFrame().speed * 2;
1747 if (currentFrame().speed > targetFrame().speed) {
1748 speed = currentFrame().speed * 2;
1751 speed = transspeed * 2;
1755 for (int i = 0; i < skeleton.joints.size(); i++) {
1756 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1757 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);
1759 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1760 change.x = (float)(Random() % 100) / 100;
1761 change.y = (float)(Random() % 100) / 100;
1762 change.z = (float)(Random() % 100) / 100;
1763 skeleton.joints[i].velocity += change;
1764 skeleton.joints[abs(Random() % skeleton.joints.size())].velocity -= change;
1766 change.x = (float)(Random() % 100) / 100;
1767 change.y = (float)(Random() % 100) / 100;
1768 change.z = (float)(Random() % 100) / 100;
1769 skeleton.joints[i].velchange += change;
1770 skeleton.joints[abs(Random() % skeleton.joints.size())].velchange -= change;
1773 if (checkcollision) {
1780 for (j = 0; j < skeleton.joints.size(); j++) {
1781 average += skeleton.joints[j].position;
1785 coords += average * scale;
1786 for (j = 0; j < skeleton.joints.size(); j++) {
1787 skeleton.joints[j].position -= average;
1790 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1791 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1792 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1793 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1794 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1797 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1798 coords.x = lowpoint.x;
1799 coords.z = lowpoint.z;
1808 for (int i = 0; i < skeleton.joints.size(); i++) {
1809 velocity += skeleton.joints[i].velocity * scale;
1811 velocity /= skeleton.joints.size();
1814 if (Random() % 2 == 0) {
1815 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1816 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1817 weapons[weaponids[0]].velocity.x += .01;
1820 weaponids[0] = weaponids[num_weapons];
1821 if (weaponstuck == num_weapons)
1825 for (unsigned i = 0; i < Person::players.size(); i++) {
1826 Person::players[i]->wentforweapon = 0;
1831 animTarget = bounceidleanim;
1832 animCurrent = bounceidleanim;
1842 void Person::FootLand(bodypart whichfoot, float opacity)
1844 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1845 cerr << "FootLand called on wrong bodypart" << endl;
1848 static XYZ terrainlight;
1849 static XYZ footvel, footpoint;
1850 if (opacity >= 1 || skiddelay <= 0) {
1853 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1854 if (distsq(&footpoint, &viewer))
1855 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1856 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1857 footvel = velocity / 5;
1860 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1861 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1862 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1863 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1864 if (environment == snowyenvironment) {
1865 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1867 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1869 } else if (environment == grassyenvironment) {
1870 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1871 } else if (environment == desertenvironment) {
1872 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1874 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1878 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1879 footvel = velocity / 5;
1882 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1883 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1884 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1891 * make a puff effect at a body part (dust effect?)
1893 void Person::Puff(int whichlabel)
1895 static XYZ footvel, footpoint;
1898 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1899 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1903 * I think I added this in an attempt to clean up code
1905 void Person::setAnimation(int animation)
1907 animTarget = animation;
1916 void Person::DoAnimations()
1918 if (!skeleton.free) {
1919 static float oldtarget;
1921 if (isIdle() && animCurrent != getIdle())
1922 normalsupdatedelay = 0;
1924 if (animTarget == tempanim || animCurrent == tempanim) {
1925 Animation::animations[tempanim] = tempanimation;
1927 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1933 vel[0] = velocity.x;
1934 vel[1] = velocity.y;
1935 vel[2] = velocity.z;
1938 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1939 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1941 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1943 if (!crouchkeydown && velocity.y >= -15)
1946 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1951 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1953 if (normaldotproduct(targfacing, velocity) >= -.3)
1954 animTarget = flipanim;
1956 animTarget = backflipanim;
1957 crouchtogglekeydown = 1;
1965 if (Animation::animations[animTarget].attack != reversed)
1967 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1968 crouchtogglekeydown = 0;
1969 if (aitype == playercontrolled)
1972 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1975 crouchtogglekeydown = 1;
1979 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1981 normalsupdatedelay = 0;
1985 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1987 emit_sound_at(fireendsound, coords);
1988 pause_sound(stream_firesound);
1992 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1993 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1995 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1996 if (normaldotproduct(victim->facing, facing) > 0)
1997 victim->animTarget = rabbittackledbackanim;
1999 victim->animTarget = rabbittackledfrontanim;
2000 victim->frameTarget = 2;
2003 victim->targetyaw = yaw;
2004 if (victim->aitype == gethelptype)
2005 victim->DoDamage(victim->damagetolerance - victim->damage);
2006 //victim->DoDamage(30);
2007 if (creature == wolftype) {
2009 emit_sound_at(clawslicesound, victim->coords);
2011 victim->DoBloodBig(1 / victim->armorhead, 210);
2013 award_bonus(id, TackleBonus,
2014 victim->aitype == gethelptype ? 50 : 0);
2018 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2019 if (weapons[weaponids[0]].getType() == knife) {
2020 if (weaponactive == -1)
2022 else if (weaponactive == 0)
2025 if (weaponactive == -1) {
2026 emit_sound_at(knifesheathesound, coords);
2028 if (weaponactive != -1) {
2029 emit_sound_at(knifedrawsound, coords, 128);
2032 drawtogglekeydown = 1;
2035 if (tutoriallevel != 1 || id == 0)
2036 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2039 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2040 if (targetFrame().label == 1)
2041 whichsound = footstepsound;
2043 whichsound = footstepsound2;
2044 if (targetFrame().label == 1)
2045 FootLand(leftfoot, 1);
2046 if (targetFrame().label == 2)
2047 FootLand(rightfoot, 1);
2048 if (targetFrame().label == 3 && isRun()) {
2049 FootLand(rightfoot, 1);
2050 FootLand(leftfoot, 1);
2054 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2055 if (targetFrame().label == 1)
2056 whichsound = footstepsound3;
2058 whichsound = footstepsound4;
2062 if (targetFrame().label == 1)
2063 whichsound = footstepsound3;
2065 whichsound = footstepsound4;
2067 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2068 if (Animation::animations[animTarget].attack != neutral) {
2069 unsigned r = abs(Random() % 3);
2071 whichsound = lowwhooshsound;
2073 whichsound = midwhooshsound;
2075 whichsound = highwhooshsound;
2077 if (Animation::animations[animTarget].attack == neutral)
2078 whichsound = movewhooshsound;
2079 } else if (targetFrame().label == 4)
2080 whichsound = knifeswishsound;
2081 if (targetFrame().label == 8 && tutoriallevel != 1)
2082 whichsound = landsound2;
2084 emit_sound_at(whichsound, coords, 256.);
2087 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2088 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2089 addEnvSound(coords, 15);
2091 addEnvSound(coords, 6);
2095 if (targetFrame().label == 3) {
2097 emit_sound_at(whichsound, coords, 128.);
2102 if (tutoriallevel != 1 || id == 0)
2103 if (speechdelay <= 0)
2104 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2105 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2106 int whichsound = -1;
2107 if (targetFrame().label == 4 && aitype != playercontrolled) {
2108 if (Animation::animations[animTarget].attack != neutral) {
2109 unsigned r = abs(Random() % 4);
2110 if (creature == rabbittype) {
2111 if (r == 0) whichsound = rabbitattacksound;
2112 if (r == 1) whichsound = rabbitattack2sound;
2113 if (r == 2) whichsound = rabbitattack3sound;
2114 if (r == 3) whichsound = rabbitattack4sound;
2116 if (creature == wolftype) {
2117 if (r == 0) whichsound = barksound;
2118 if (r == 1) whichsound = bark2sound;
2119 if (r == 2) whichsound = bark3sound;
2120 if (r == 3) whichsound = barkgrowlsound;
2126 if (whichsound != -1) {
2127 emit_sound_at(whichsound, coords);
2133 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2134 FootLand(leftfoot, 1);
2135 FootLand(rightfoot, 1);
2139 currentoffset = targetoffset;
2140 frameTarget = frameCurrent;
2141 animCurrent = animTarget;
2144 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2145 for (unsigned i = 0; i < weapons.size(); i++) {
2146 if (weapons[i].owner == -1)
2147 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2148 if (distsq(&coords, &weapons[i].position) >= 1) {
2149 if (weapons[i].getType() != staff) {
2150 emit_sound_at(knifedrawsound, coords, 128.);
2159 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2160 for (unsigned i = 0; i < weapons.size(); i++) {
2161 bool willwork = true;
2162 if (weapons[i].owner != -1)
2163 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2164 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2165 if (Person::players[weapons[i].owner]->num_weapons > 1)
2167 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2168 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2169 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2170 bool fleshstuck = false;
2171 if (weapons[i].owner != -1)
2172 if (victim->weaponstuck != -1) {
2173 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2178 emit_sound_at(fleshstabremovesound, coords, 128.);
2180 if (weapons[i].getType() != staff) {
2181 emit_sound_at(knifedrawsound, coords, 128.);
2184 if (weapons[i].owner != -1) {
2185 victim = Person::players[weapons[i].owner];
2186 if (victim->num_weapons == 1)
2187 victim->num_weapons = 0;
2189 victim->num_weapons = 1;
2191 //victim->weaponactive=-1;
2192 victim->skeleton.longdead = 0;
2193 victim->skeleton.free = 1;
2194 victim->skeleton.broken = 0;
2196 for (int j = 0; j < victim->skeleton.joints.size(); j++) {
2197 victim->skeleton.joints[j].velchange = 0;
2198 victim->skeleton.joints[j].locked = 0;
2204 Normalise(&relative);
2205 XYZ footvel, footpoint;
2207 footpoint = weapons[i].position;
2208 if (victim->weaponstuck != -1) {
2209 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2211 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2212 weapons[i].bloody = 2;
2213 weapons[i].blooddrip = 5;
2214 victim->weaponstuck = -1;
2217 if (victim->num_weapons > 0) {
2218 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2219 victim->weaponstuck = 0;
2220 if (victim->weaponids[0] == int(i))
2221 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2224 victim->jointVel(abdomen) += relative * 6;
2225 victim->jointVel(neck) += relative * 6;
2226 victim->jointVel(rightshoulder) += relative * 6;
2227 victim->jointVel(leftshoulder) += relative * 6;
2235 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2236 if (weaponactive == -1)
2238 else if (weaponactive == 0) {
2240 if (num_weapons == 2) {
2242 buffer = weaponids[0];
2243 weaponids[0] = weaponids[1];
2244 weaponids[1] = buffer;
2247 if (weaponactive == -1) {
2248 emit_sound_at(knifesheathesound, coords, 128.);
2250 if (weaponactive != -1) {
2251 emit_sound_at(knifedrawsound, coords, 128.);
2256 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2257 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2258 Normalise(&rotatetarget);
2259 targetyaw = -asin(0 - rotatetarget.x);
2260 targetyaw *= 360 / 6.28;
2261 if (rotatetarget.z < 0)
2262 targetyaw = 180 - targetyaw;
2264 if (animTarget == walljumprightkickanim)
2266 if (animTarget == walljumpleftkickanim)
2272 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2275 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2280 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2281 animTarget = rabbittackleanim;
2283 emit_sound_at(jumpsound, coords);
2291 targetloc = velocity;
2292 Normalise(&targetloc);
2293 targetloc += coords;
2294 for (unsigned i = 0; i < Person::players.size(); i++) {
2296 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2297 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2301 if (closestid != -1)
2302 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2304 victim = Person::players[closestid];
2305 coords = victim->coords;
2306 animCurrent = rabbittacklinganim;
2307 animTarget = rabbittacklinganim;
2311 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2312 rotatetarget = coords - victim->coords;
2313 Normalise(&rotatetarget);
2314 targetyaw = -asin(0 - rotatetarget.x);
2315 targetyaw *= 360 / 6.28;
2316 if (rotatetarget.z < 0)
2317 targetyaw = 180 - targetyaw;
2319 if (animTarget != rabbitrunninganim) {
2320 emit_sound_at(jumpsound, coords, 128.);
2326 float damagemult = 1 * power;
2327 if (creature == wolftype)
2328 damagemult = 2.5 * power;
2330 damagemult /= victim->damagetolerance / 200;
2332 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)) {
2333 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2334 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2338 if (Random() % 2 || creature == wolftype) {
2341 if (creature == wolftype)
2344 if (tutoriallevel != 1) {
2345 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2347 if (creature == wolftype) {
2348 emit_sound_at(clawslicesound, victim->coords, 128.);
2350 victim->DoBloodBig(2 / victim->armorhead, 175);
2354 relative = victim->coords - coords;
2356 Normalise(&relative);
2357 relative = DoRotation(relative, 0, -90, 0);
2358 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2359 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2361 victim->jointVel(head) += relative * damagemult * 200;
2363 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2369 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2370 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2374 if (Random() % 2 || creature == wolftype) {
2376 if (creature == wolftype)
2379 emit_sound_at(whooshhitsound, victim->coords);
2380 if (creature == wolftype) {
2381 emit_sound_at(clawslicesound, victim->coords, 128.);
2383 victim->DoBloodBig(2, 175);
2387 relative = victim->coords - coords;
2389 Normalise(&relative);
2391 Normalise(&relative);
2392 relative = DoRotation(relative, 0, 90, 0);
2393 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2394 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2396 victim->jointVel(head) += relative * damagemult * 100;
2398 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2402 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2403 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2409 if (tutoriallevel != 1) {
2410 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2412 if (creature == wolftype) {
2413 emit_sound_at(clawslicesound, victim->coords, 128.);
2415 victim->DoBloodBig(2 / victim->armorhead, 175);
2421 Normalise(&relative);
2422 relative = DoRotation(relative, 0, -90, 0);
2423 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2424 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2426 victim->jointVel(head) += relative * damagemult * 200;
2428 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2430 if (victim->damage > victim->damagetolerance)
2431 award_bonus(id, style);
2437 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2438 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2444 if (tutoriallevel != 1) {
2445 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2447 if (creature == wolftype) {
2448 emit_sound_at(clawslicesound, victim->coords, 128.);
2450 victim->DoBloodBig(2 / victim->armorhead, 175);
2456 Normalise(&relative);
2457 relative = DoRotation(relative, 0, 90, 0);
2458 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2459 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2461 victim->jointVel(head) += relative * damagemult * 200;
2463 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2465 if (victim->damage > victim->damagetolerance)
2466 award_bonus(id, style);
2472 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2473 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2481 emit_sound_at(whooshhitsound, victim->coords);
2484 relative = victim->coords - coords;
2486 Normalise(&relative);
2487 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2488 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2490 victim->jointVel(head) += relative * damagemult * 100;
2492 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2496 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2497 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2501 emit_sound_at(whooshhitsound, victim->coords, 128.);
2503 victim->skeleton.longdead = 0;
2504 victim->skeleton.free = 1;
2505 victim->skeleton.broken = 0;
2506 victim->skeleton.spinny = 1;
2508 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2509 victim->skeleton.joints[i].velchange = 0;
2510 victim->skeleton.joints[i].delay = 0;
2511 victim->skeleton.joints[i].locked = 0;
2512 //victim->skeleton.joints[i].velocity=0;
2518 Normalise(&relative);
2519 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2520 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2521 victim->skeleton.joints[i].position.y += relative.y * .3;
2522 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2523 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2525 victim->Puff(abdomen);
2526 victim->jointVel(abdomen).y = relative.y * 400;
2530 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2531 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2535 if (tutoriallevel != 1) {
2536 emit_sound_at(heavyimpactsound, coords, 128.);
2539 relative = victim->coords - coords;
2541 Normalise(&relative);
2542 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2543 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2545 victim->Puff(abdomen);
2546 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2550 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2551 victim->jointVel(abdomen) += relative * damagemult * 300;
2555 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2556 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2560 if (tutoriallevel != 1) {
2561 emit_sound_at(thudsound, coords);
2564 victim->skeleton.longdead = 0;
2565 victim->skeleton.free = 1;
2566 victim->skeleton.broken = 0;
2567 victim->skeleton.spinny = 1;
2569 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2570 victim->skeleton.joints[i].velchange = 0;
2571 //victim->skeleton.joints[i].delay=0;
2572 victim->skeleton.joints[i].locked = 0;
2575 relative = victim->coords - coords;
2576 Normalise(&relative);
2578 Normalise(&relative);
2579 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2580 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2585 victim->Puff(abdomen);
2586 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2587 victim->jointVel(abdomen) += relative * damagemult * 200;
2596 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2599 if (!victim->skeleton.free)
2603 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2604 emit_sound_at(knifesheathesound, coords, 128.);
2607 if (victim && hasvictim) {
2608 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2610 XYZ where, startpoint, endpoint, movepoint, colpoint;
2611 float rotationpoint;
2613 if (weapons[weaponids[weaponactive]].getType() == knife) {
2614 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2615 where -= victim->coords;
2616 if (!victim->skeleton.free)
2617 where = DoRotation(where, 0, -victim->yaw, 0);
2620 startpoint.y += 100;
2624 if (weapons[weaponids[weaponactive]].getType() == sword) {
2625 where = weapons[weaponids[weaponactive]].position;
2626 where -= victim->coords;
2627 if (!victim->skeleton.free)
2628 where = DoRotation(where, 0, -victim->yaw, 0);
2630 where = weapons[weaponids[weaponactive]].tippoint;
2631 where -= victim->coords;
2632 if (!victim->skeleton.free)
2633 where = DoRotation(where, 0, -victim->yaw, 0);
2636 if (weapons[weaponids[weaponactive]].getType() == staff) {
2637 where = weapons[weaponids[weaponactive]].position;
2638 where -= victim->coords;
2639 if (!victim->skeleton.free)
2640 where = DoRotation(where, 0, -victim->yaw, 0);
2642 where = weapons[weaponids[weaponactive]].tippoint;
2643 where -= victim->coords;
2644 if (!victim->skeleton.free)
2645 where = DoRotation(where, 0, -victim->yaw, 0);
2650 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2652 if (whichtri != -1) {
2653 if (victim->dead != 2) {
2654 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2656 award_bonus(id, FinishedBonus);
2659 weapons[weaponids[weaponactive]].bloody = 2;
2661 victim->skeleton.longdead = 0;
2662 victim->skeleton.free = 1;
2663 victim->skeleton.broken = 0;
2665 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2666 victim->skeleton.joints[i].velchange = 0;
2667 victim->skeleton.joints[i].locked = 0;
2668 //victim->skeleton.joints[i].velocity=0;
2670 emit_sound_at(fleshstabsound, coords, 128);
2673 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2674 weapons[weaponids[weaponactive]].blooddrip += 5;
2675 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2677 if (whichtri == -1) {
2679 emit_sound_at(knifesheathesound, coords, 128.);
2685 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2687 emit_sound_at(knifedrawsound, coords, 128);
2690 if (victim && hasvictim) {
2691 XYZ footvel, footpoint;
2693 emit_sound_at(fleshstabremovesound, coords, 128.);
2696 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2698 if (weapons[weaponids[weaponactive]].getType() == sword) {
2699 XYZ where, startpoint, endpoint, movepoint;
2700 float rotationpoint;
2703 where = weapons[weaponids[weaponactive]].position;
2704 where -= victim->coords;
2705 if (!victim->skeleton.free)
2706 where = DoRotation(where, 0, -victim->yaw, 0);
2708 where = weapons[weaponids[weaponactive]].tippoint;
2709 where -= victim->coords;
2710 if (!victim->skeleton.free)
2711 where = DoRotation(where, 0, -victim->yaw, 0);
2716 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2717 footpoint += victim->coords;
2719 if (whichtri == -1) {
2720 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2723 if (weapons[weaponids[weaponactive]].getType() == staff) {
2724 XYZ where, startpoint, endpoint, movepoint;
2725 float rotationpoint;
2728 where = weapons[weaponids[weaponactive]].position;
2729 where -= victim->coords;
2730 if (!victim->skeleton.free)
2731 where = DoRotation(where, 0, -victim->yaw, 0);
2733 where = weapons[weaponids[weaponactive]].tippoint;
2734 where -= victim->coords;
2735 if (!victim->skeleton.free)
2736 where = DoRotation(where, 0, -victim->yaw, 0);
2741 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2742 footpoint += victim->coords;
2744 if (whichtri == -1) {
2745 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2748 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2750 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2751 victim->skeleton.longdead = 0;
2752 victim->skeleton.free = 1;
2753 victim->skeleton.broken = 0;
2755 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2756 victim->skeleton.joints[i].velchange = 0;
2757 victim->skeleton.joints[i].locked = 0;
2758 //victim->skeleton.joints[i].velocity=0;
2764 Normalise(&relative);
2765 //victim->Puff(abdomen);
2767 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2769 if (victim->bloodloss < victim->damagetolerance) {
2770 victim->bloodloss += 1000;
2774 victim->jointVel(abdomen) += relative * damagemult * 20;
2778 if (!hasvictim && onterrain) {
2779 weapons[weaponids[weaponactive]].bloody = 0;
2780 weapons[weaponids[weaponactive]].blooddrip = 0;
2784 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2785 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2793 if (tutoriallevel != 1) {
2794 emit_sound_at(heavyimpactsound, victim->coords, 128);
2799 relative = victim->coords - coords;
2801 Normalise(&relative);
2802 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2803 victim->skeleton.joints[i].velocity = relative * 30;
2805 victim->jointVel(head) += relative * damagemult * 150;
2807 victim->frameTarget = 0;
2808 victim->animTarget = staggerbackhardanim;
2809 victim->targetyaw = targetyaw + 180;
2811 victim->stunned = 1;
2814 victim->Puff(abdomen);
2815 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2822 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2823 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2827 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2828 if (tutoriallevel != 1) {
2829 emit_sound_at(thudsound, victim->coords);
2831 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2832 if (tutoriallevel != 1) {
2833 emit_sound_at(whooshhitsound, victim->coords);
2836 if (tutoriallevel != 1) {
2837 emit_sound_at(heavyimpactsound, victim->coords);
2841 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2844 relative = victim->coords - coords;
2846 Normalise(&relative);
2848 Normalise(&relative);
2849 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2850 victim->skeleton.joints[i].velocity = relative * 5;
2852 victim->jointVel(abdomen) += relative * damagemult * 400;
2854 victim->frameTarget = 0;
2855 victim->animTarget = staggerbackhardanim;
2856 victim->targetyaw = targetyaw + 180;
2858 victim->stunned = 1;
2860 victim->Puff(abdomen);
2861 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2867 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2868 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2869 if (victim->id == 0)
2871 emit_sound_at(landsound2, victim->coords);
2877 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2878 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2879 if (victim->id == 0)
2882 if (weaponactive != -1) {
2883 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2884 if (weapons[victim->weaponids[0]].getType() == staff)
2885 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2886 if (weapons[weaponids[0]].getType() == staff)
2887 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2889 emit_sound_at(swordstaffsound, victim->coords);
2891 emit_sound_at(metalhitsound, victim->coords);
2899 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2900 if (weaponactive != -1) {
2903 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);
2905 weapons[weaponids[0]].thrown(aim * 50);
2908 weaponids[0] = weaponids[num_weapons];
2914 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2916 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2918 if (tutoriallevel != 1)
2919 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2921 award_bonus(id, Slicebonus);
2922 if (tutoriallevel != 1) {
2923 emit_sound_at(knifeslicesound, victim->coords);
2925 //victim->jointVel(abdomen)+=relative*damagemult*200;
2926 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2927 if (victim->id != 0 || difficulty == 2) {
2928 victim->frameTarget = 0;
2929 victim->animTarget = staggerbackhardanim;
2930 victim->targetyaw = targetyaw + 180;
2934 victim->lowreversaldelay = 0;
2935 victim->highreversaldelay = 0;
2936 if (aitype != playercontrolled)
2937 weaponmissdelay = .6;
2939 if (tutoriallevel != 1)
2940 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2941 weapons[weaponids[weaponactive]].bloody = 1;
2942 if (tutoriallevel != 1)
2943 weapons[weaponids[weaponactive]].blooddrip += 3;
2945 XYZ footvel, footpoint;
2947 if (skeleton.free) {
2948 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2950 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2952 if (tutoriallevel != 1) {
2954 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2955 footvel = DoRotation(facing, 0, 90, 0) * .8;
2957 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2958 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2959 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2960 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2962 if (tutoriallevel == 1) {
2963 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2965 victim->DoDamage(damagemult * 0);
2968 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2969 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2970 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2971 award_bonus(id, Slashbonus);
2973 if (tutoriallevel != 1) {
2974 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2975 victim->DoBloodBig(2 / victim->armorhigh, 190);
2977 victim->DoBloodBig(2 / victim->armorhigh, 185);
2978 victim->deathbleeding = 1;
2979 emit_sound_at(swordslicesound, victim->coords);
2981 //victim->jointVel(abdomen)+=relative*damagemult*200;
2982 if (tutoriallevel != 1) {
2983 victim->frameTarget = 0;
2984 victim->animTarget = staggerbackhardanim;
2985 victim->targetyaw = targetyaw + 180;
2989 if (tutoriallevel != 1) {
2990 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2991 weapons[weaponids[weaponactive]].bloody = 1;
2992 weapons[weaponids[weaponactive]].blooddrip += 3;
2994 float bloodlossamount;
2995 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2996 victim->bloodloss += bloodlossamount / victim->armorhigh;
2997 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2998 victim->DoDamage(damagemult * 0);
3000 XYZ footvel, footpoint;
3002 if (skeleton.free) {
3003 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3005 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3008 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3009 footvel = DoRotation(facing, 0, 90, 0) * .8;
3011 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3012 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3013 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3014 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3017 if (victim->weaponactive != -1) {
3018 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3019 if (weapons[victim->weaponids[0]].getType() == staff)
3020 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3021 if (weapons[weaponids[0]].getType() == staff)
3022 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3024 emit_sound_at(swordstaffsound, victim->coords);
3026 emit_sound_at(metalhitsound, victim->coords);
3032 victim->Puff(righthand);
3034 victim->frameTarget = 0;
3035 victim->animTarget = staggerbackhighanim;
3036 victim->targetyaw = targetyaw + 180;
3038 aim = DoRotation(facing, 0, 90, 0) * 21;
3040 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3041 victim->num_weapons--;
3042 if (victim->num_weapons) {
3043 victim->weaponids[0] = victim->weaponids[num_weapons];
3044 if (victim->weaponstuck == victim->num_weapons)
3045 victim->weaponstuck = 0;
3047 victim->weaponactive = -1;
3048 for (unsigned i = 0; i < Person::players.size(); i++) {
3049 Person::players[i]->wentforweapon = 0;
3056 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3057 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3058 if (tutoriallevel != 1) {
3059 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3063 if (Random() % 2 || creature == wolftype) {
3066 emit_sound_at(staffheadsound, victim->coords);
3070 relative = victim->coords - coords;
3072 Normalise(&relative);
3073 relative = DoRotation(relative, 0, 90, 0);
3075 Normalise(&relative);
3076 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3077 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3079 victim->jointVel(head) += relative * damagemult * 230;
3080 victim->jointVel(neck) += relative * damagemult * 230;
3082 if (tutoriallevel != 1) {
3083 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3085 award_bonus(id, solidhit, 30);
3090 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3091 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3092 if (tutoriallevel != 1) {
3093 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3097 if (Random() % 2 || creature == wolftype) {
3100 emit_sound_at(staffheadsound, victim->coords);
3104 relative = victim->coords - coords;
3106 Normalise(&relative);
3107 relative = DoRotation(relative, 0, -90, 0);
3108 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3109 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3111 victim->jointVel(head) += relative * damagemult * 220;
3112 victim->jointVel(neck) += relative * damagemult * 220;
3114 if (tutoriallevel != 1) {
3115 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3117 award_bonus(id, solidhit, 60);
3122 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3123 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3125 if (tutoriallevel != 1) {
3127 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3130 if (Random() % 2 || creature == wolftype) {
3133 emit_sound_at(staffbodysound, victim->coords);
3135 victim->skeleton.longdead = 0;
3136 victim->skeleton.free = 1;
3137 victim->skeleton.broken = 0;
3139 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3140 victim->skeleton.joints[i].velchange = 0;
3141 victim->skeleton.joints[i].locked = 0;
3142 //victim->skeleton.joints[i].velocity=0;
3149 Normalise(&relative);
3150 if (!victim->dead) {
3151 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3152 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3154 victim->jointVel(abdomen) += relative * damagemult * 40;
3157 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3158 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3161 victim->Puff(abdomen);
3162 if (tutoriallevel != 1) {
3163 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3165 if (!victim->dead) {
3166 award_bonus(id, solidhit, 40);
3172 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3173 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3178 relative = victim->coords - coords;
3180 Normalise(&relative);
3184 if (Animation::animations[victim->animTarget].height == lowheight) {
3190 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3191 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3193 victim->jointVel(head) += relative * damagemult * 200;
3194 if (tutoriallevel != 1) {
3195 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3198 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3199 if (victim->howactive == typesleeping)
3200 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3201 if (creature == wolftype) {
3202 emit_sound_at(clawslicesound, victim->coords, 128.);
3204 victim->DoBloodBig(2 / victim->armorhead, 175);
3207 if (victim->damage >= victim->damagetolerance)
3209 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3210 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3212 victim->jointVel(abdomen) += relative * damagemult * 200;
3213 victim->frameTarget = 0;
3214 victim->animTarget = staggerbackhighanim;
3215 victim->targetyaw = targetyaw + 180;
3217 if (tutoriallevel != 1) {
3218 emit_sound_at(landsound2, victim->coords, 128.);
3220 victim->Puff(abdomen);
3221 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3222 if (creature == wolftype) {
3223 emit_sound_at(clawslicesound, victim->coords, 128.);
3225 victim->DoBloodBig(2 / victim->armorhigh, 170);
3232 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3233 if ((victim->animTarget != jumpupanim) &&
3234 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3235 (victim != this->shared_from_this())) {
3239 if (tutoriallevel != 1) {
3240 emit_sound_at(landsound2, victim->coords, 128.);
3243 relative = victim->coords - coords;
3245 Normalise(&relative);
3247 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3250 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3251 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3253 relative = DoRotation(relative, 0, -90, 0);
3255 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3256 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)
3257 victim->skeleton.joints[i].velocity = relative * 80;
3259 victim->Puff(rightankle);
3260 victim->Puff(leftankle);
3261 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3263 if (victim->damage >= victim->damagetolerance)
3265 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3266 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3268 relative = DoRotation(relative, 0, -90, 0);
3269 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3270 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)
3271 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3273 victim->jointVel(abdomen) += relative * damagemult * 200;
3274 victim->frameTarget = 0;
3275 victim->animTarget = staggerbackhighanim;
3276 victim->targetyaw = targetyaw + 180;
3278 if (tutoriallevel != 1) {
3279 emit_sound_at(landsound2, victim->coords, 128.);
3281 victim->Puff(abdomen);
3282 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3290 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3291 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3299 if (tutoriallevel != 1) {
3300 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3302 if (creature == wolftype) {
3303 emit_sound_at(clawslicesound, victim->coords, 128);
3305 victim->DoBloodBig(2 / victim->armorhigh, 170);
3309 relative = victim->coords - oldcoords;
3311 Normalise(&relative);
3312 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3313 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3315 victim->jointVel(abdomen) += relative * damagemult * 200;
3316 victim->Puff(abdomen);
3317 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3319 award_bonus(id, Reversal);
3322 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3323 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3324 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3325 takeWeapon(victim->weaponids[victim->weaponactive]);
3326 victim->num_weapons--;
3327 if (victim->num_weapons > 0) {
3328 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3330 victim->weaponactive = -1;
3335 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3343 emit_sound_at(whooshhitsound, victim->coords, 128.);
3346 relative = victim->coords - oldcoords;
3348 Normalise(&relative);
3349 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3350 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3352 victim->jointVel(abdomen) += relative * damagemult * 200;
3354 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3357 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3366 award_bonus(id, staffreversebonus);
3368 if (tutoriallevel != 1) {
3369 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3372 award_bonus(id, staffreversebonus); // Huh, again?
3375 relative = victim->coords - oldcoords;
3377 Normalise(&relative);
3378 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3379 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3381 victim->jointVel(abdomen) += relative * damagemult * 200;
3383 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3386 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3392 Normalise(&relative);
3394 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3395 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3397 victim->jointVel(lefthand) *= .1;
3398 victim->jointVel(leftwrist) *= .2;
3399 victim->jointVel(leftelbow) *= .5;
3400 victim->jointVel(leftshoulder) *= .7;
3401 victim->jointVel(righthand) *= .1;
3402 victim->jointVel(rightwrist) *= .2;
3403 victim->jointVel(rightelbow) *= .5;
3404 victim->jointVel(rightshoulder) *= .7;
3406 victim->Puff(abdomen);
3407 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3409 award_bonus(id, Reversal);
3413 if (weaponactive != -1 || creature == wolftype)
3415 if (creature == rabbittype && weaponactive != -1)
3416 if (weapons[weaponids[0]].getType() == staff)
3419 if (weaponactive != -1) {
3420 victim->DoBloodBig(2 / victim->armorhigh, 225);
3421 emit_sound_at(knifeslicesound, victim->coords);
3422 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3423 weapons[weaponids[weaponactive]].bloody = 1;
3424 weapons[weaponids[weaponactive]].blooddrip += 3;
3426 if (weaponactive == -1 && creature == wolftype) {
3427 emit_sound_at(clawslicesound, victim->coords, 128.);
3429 victim->DoBloodBig(2 / victim->armorhigh, 175);
3436 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3442 Normalise(&relative);
3444 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3445 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3447 victim->jointVel(lefthand) *= .1 - 1;
3448 victim->jointVel(leftwrist) *= .2 - 1;
3449 victim->jointVel(leftelbow) *= .5 - 1;
3450 victim->jointVel(leftshoulder) *= .7 - 1;
3451 victim->jointVel(righthand) *= .1 - 1;
3452 victim->jointVel(rightwrist) *= .2 - 1;
3453 victim->jointVel(rightelbow) *= .5 - 1;
3454 victim->jointVel(rightshoulder) *= .7 - 1;
3456 award_bonus(id, swordreversebonus);
3459 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3467 if (tutoriallevel != 1) {
3468 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3472 relative = victim->coords - oldcoords;
3474 Normalise(&relative);
3475 relative = DoRotation(relative, 0, -90, 0);
3476 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3477 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3479 victim->jointVel(abdomen) += relative * damagemult * 200;
3480 victim->Puff(abdomen);
3481 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3483 award_bonus(id, Reversal);
3486 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3489 victim->skeleton.spinny = 0;
3491 relative = facing * -1;
3493 Normalise(&relative);
3494 if (victim->id == 0)
3496 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3497 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3499 victim->damage = victim->damagetolerance;
3500 victim->permanentdamage = victim->damagetolerance - 1;
3503 if (weaponactive != -1 || creature == wolftype)
3505 if (creature == rabbittype && weaponactive != -1)
3506 if (weapons[weaponids[0]].getType() == staff)
3509 if (weaponactive != -1) {
3510 victim->DoBloodBig(200, 225);
3511 emit_sound_at(knifeslicesound, victim->coords);
3513 weapons[weaponids[weaponactive]].bloody = 2;
3514 weapons[weaponids[weaponactive]].blooddrip += 5;
3517 if (creature == wolftype && weaponactive == -1) {
3518 emit_sound_at(clawslicesound, victim->coords, 128.);
3520 victim->DoBloodBig(2, 175);
3523 award_bonus(id, spinecrusher);
3526 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3527 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3529 if (animTarget == knifefollowanim)
3530 victim->DoBloodBig(200, 210);
3531 if (animTarget == knifesneakattackanim) {
3532 XYZ footvel, footpoint;
3534 footpoint = weapons[weaponids[0]].tippoint;
3536 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3537 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3538 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3539 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3541 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3542 victim->DoBloodBig(200, 195);
3543 award_bonus(id, tracheotomy);
3545 if (animTarget == knifefollowanim) {
3546 award_bonus(id, Stabbonus);
3547 XYZ footvel, footpoint;
3549 footpoint = weapons[weaponids[0]].tippoint;
3551 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3552 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3553 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3554 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3555 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3556 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3559 victim->bloodloss += 10000;
3560 victim->velocity = 0;
3561 emit_sound_at(fleshstabsound, victim->coords);
3563 weapons[weaponids[weaponactive]].bloody = 2;
3564 weapons[weaponids[weaponactive]].blooddrip += 5;
3568 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3570 victim->velocity = 0;
3571 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3572 victim->skeleton.joints[i].velocity = 0;
3574 if (animTarget == knifefollowanim) {
3576 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3577 victim->skeleton.joints[i].velocity = 0;
3580 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3581 emit_sound_at(fleshstabremovesound, victim->coords);
3583 weapons[weaponids[weaponactive]].bloody = 2;
3584 weapons[weaponids[weaponactive]].blooddrip += 5;
3586 XYZ footvel, footpoint;
3588 footpoint = weapons[weaponids[0]].tippoint;
3590 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3591 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3592 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3593 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3594 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3595 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3599 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3600 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3601 award_bonus(id, backstab);
3605 XYZ footvel, footpoint;
3607 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3609 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3610 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3611 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3612 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3613 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3614 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3615 victim->DoBloodBig(200, 180);
3616 victim->DoBloodBig(200, 215);
3617 victim->bloodloss += 10000;
3618 victim->velocity = 0;
3619 emit_sound_at(fleshstabsound, victim->coords);
3621 weapons[weaponids[weaponactive]].bloody = 2;
3622 weapons[weaponids[weaponactive]].blooddrip += 5;
3626 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3628 victim->velocity = 0;
3629 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3630 victim->skeleton.joints[i].velocity = 0;
3632 if (weaponactive != -1) {
3633 emit_sound_at(fleshstabremovesound, victim->coords);
3635 weapons[weaponids[weaponactive]].bloody = 2;
3636 weapons[weaponids[weaponactive]].blooddrip += 5;
3638 XYZ footvel, footpoint;
3640 footpoint = weapons[weaponids[0]].tippoint;
3642 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3643 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3644 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3645 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3646 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3647 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3651 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3659 if (weaponactive == -1) {
3660 if (tutoriallevel != 1) {
3661 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3666 if (weaponactive != -1 || creature == wolftype)
3668 if (creature == rabbittype && weaponactive != -1)
3669 if (weapons[weaponids[0]].getType() == staff)
3672 if (weaponactive != -1) {
3673 victim->DoBloodBig(2 / victim->armorhead, 225);
3674 emit_sound_at(knifeslicesound, victim->coords);
3675 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3676 weapons[weaponids[weaponactive]].bloody = 1;
3677 weapons[weaponids[weaponactive]].blooddrip += 3;
3679 if (weaponactive == -1 && creature == wolftype) {
3680 emit_sound_at(clawslicesound, victim->coords, 128.);
3682 victim->DoBloodBig(2 / victim->armorhead, 175);
3686 award_bonus(id, Reversal);
3691 relative = facing * -1;
3693 Normalise(&relative);
3694 relative = DoRotation(relative, 0, 90, 0);
3696 Normalise(&relative);
3697 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3698 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3700 victim->jointVel(head) += relative * damagemult * 200;
3701 if (victim->damage < victim->damagetolerance - 100)
3702 victim->velocity = relative * 200;
3703 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3704 victim->velocity = 0;
3707 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))) {
3711 relative = facing * -1;
3713 Normalise(&relative);
3714 relative = DoRotation(relative, 0, 90, 0);
3716 Normalise(&relative);
3717 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3718 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3720 victim->jointVel(head) += relative * damagemult * 200;
3723 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3724 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3725 award_bonus(id, reverseko);
3731 if (frameTarget > Animation::animations[animCurrent].frames.size() - 1) {
3734 animTarget = getIdle();
3735 FootLand(leftfoot, 1);
3736 FootLand(rightfoot, 1);
3738 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3739 animTarget = rollanim;
3741 emit_sound_at(movewhooshsound, coords, 128.);
3743 if (animCurrent == staggerbackhighanim) {
3744 animTarget = getIdle();
3746 if (animCurrent == staggerbackhardanim) {
3747 animTarget = getIdle();
3749 if (animCurrent == removeknifeanim) {
3750 animTarget = getIdle();
3752 if (animCurrent == crouchremoveknifeanim) {
3753 animTarget = getCrouch();
3755 if (animCurrent == backhandspringanim) {
3756 animTarget = getIdle();
3758 if (animCurrent == dodgebackanim) {
3759 animTarget = getIdle();
3761 if (animCurrent == drawleftanim) {
3762 animTarget = getIdle();
3764 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3765 animTarget = getIdle();
3766 if (animCurrent == crouchdrawrightanim) {
3767 animTarget = getCrouch();
3769 if (weaponactive == -1)
3771 else if (weaponactive == 0) {
3773 if (num_weapons == 2) {
3775 buffer = weaponids[0];
3776 weaponids[0] = weaponids[1];
3777 weaponids[1] = buffer;
3781 if (weaponactive == -1) {
3782 emit_sound_at(knifesheathesound, coords, 128.);
3784 if (weaponactive != -1) {
3785 emit_sound_at(knifedrawsound, coords, 128.);
3788 if (animCurrent == rollanim) {
3789 animTarget = getCrouch();
3790 FootLand(leftfoot, 1);
3791 FootLand(rightfoot, 1);
3794 if (animTarget == walljumprightkickanim) {
3797 if (animTarget == walljumpleftkickanim) {
3800 animTarget = jumpdownanim;
3802 if (animCurrent == climbanim) {
3803 animTarget = getCrouch();
3805 coords += facing * .1;
3806 if (!isnormal(coords.x))
3817 if (animTarget == rabbitkickreversalanim) {
3818 animTarget = getCrouch();
3821 if (animTarget == jumpreversalanim) {
3822 animTarget = getCrouch();
3825 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3826 if (attackkeydown && animTarget != walljumpfrontanim) {
3828 float closestdist = -1;
3830 if (Person::players.size() > 1)
3831 for (unsigned i = 0; i < Person::players.size(); i++) {
3832 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3833 distance = distsq(&Person::players[i]->coords, &coords);
3834 if (closestdist == -1 || distance < closestdist) {
3835 closestdist = distance;
3840 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3841 victim = Person::players[closest];
3842 animTarget = walljumprightkickanim;
3844 XYZ rotatetarget = victim->coords - coords;
3845 Normalise(&rotatetarget);
3846 yaw = -asin(0 - rotatetarget.x);
3848 if (rotatetarget.z < 0)
3850 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3851 velocity = (victim->coords - coords) * 4;
3856 if (animTarget == walljumpbackanim) {
3857 animTarget = backflipanim;
3859 velocity = facing * -8;
3862 resume_stream(whooshsound);
3864 if (animTarget == walljumprightanim) {
3865 animTarget = rightflipanim;
3869 velocity = DoRotation(facing, 0, 30, 0) * -8;
3872 if (animTarget == walljumpfrontanim) {
3873 animTarget = frontflipanim;
3877 velocity = facing * 8;
3881 resume_stream(whooshsound);
3883 if (animTarget == walljumpleftanim) {
3884 if (attackkeydown) {
3886 float closestdist = -1;
3888 if (Person::players.size() > 1)
3889 for (unsigned i = 0; i < Person::players.size(); i++) {
3890 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3891 distance = distsq(&Person::players[i]->coords, &coords);
3892 if (closestdist == -1 || distance < closestdist) {
3893 closestdist = distance;
3898 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3899 victim = Person::players[closest];
3900 animTarget = walljumpleftkickanim;
3902 XYZ rotatetarget = victim->coords - coords;
3903 Normalise(&rotatetarget);
3904 yaw = -asin(0 - rotatetarget.x);
3906 if (rotatetarget.z < 0)
3908 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3909 velocity = (victim->coords - coords) * 4;
3914 if (animTarget != walljumpleftkickanim) {
3915 animTarget = leftflipanim;
3919 velocity = DoRotation(facing, 0, -30, 0) * -8;
3923 resume_stream(whooshsound);
3925 if (animTarget == sneakattackanim) {
3926 animCurrent = getCrouch();
3927 animTarget = getCrouch();
3934 transspeed = 1000000;
3935 targetheadyaw += 180;
3936 coords -= facing * .7;
3938 coords.y = terrain.getHeight(coords.x, coords.z);
3942 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3943 animTarget = getIdle();
3946 coords.y = terrain.getHeight(coords.x, coords.z);
3950 if (animCurrent == knifefollowanim) {
3951 animTarget = getIdle();
3954 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3955 float ycoords = oldcoords.y;
3956 animTarget = getStop();
3961 transspeed = 1000000;
3962 targetheadyaw += 180;
3963 if (!isnormal(coords.x))
3965 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3966 oldcoords = coords + facing * .5;
3967 else if (animCurrent == sweepreversalanim)
3968 oldcoords = coords + facing * 1.1;
3969 else if (animCurrent == upunchreversalanim) {
3970 oldcoords = coords + facing * 1.5;
3973 targetheadyaw += 180;
3976 } else if (animCurrent == knifeslashreversalanim) {
3977 oldcoords = coords + facing * .5;
3980 targetheadyaw += 90;
3983 } else if (animCurrent == staffspinhitreversalanim) {
3986 targetheadyaw += 180;
3991 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3993 oldcoords.y = ycoords;
3994 currentoffset = coords - oldcoords;
4000 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4005 if (Animation::animations[animTarget].attack == reversed) {
4007 if (animTarget == sweepreversedanim)
4009 animTarget = backhandspringanim;
4011 emit_sound_at(landsound, coords, 128);
4013 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4014 animTarget = rollanim;
4017 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4018 coords.y = oldcoords.y;
4020 if (animCurrent == knifeslashreversedanim) {
4021 animTarget = rollanim;
4026 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4027 coords.y = oldcoords.y;
4031 animTarget = jumpdownanim;
4034 animTarget = getIdle();
4036 animTarget = getIdle();
4037 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4038 animTarget = getIdle();
4040 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4041 coords.y = oldcoords.y;
4042 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4043 targetoffset.y = coords.y;
4045 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4046 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4047 currentoffset.y -= (coords.y - targetoffset.y);
4048 coords.y = targetoffset.y;
4050 normalsupdatedelay = 0;
4052 if (animCurrent == upunchanim) {
4053 animTarget = getStop();
4054 normalsupdatedelay = 0;
4057 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4061 if (num_weapons > 0)
4062 if (weapons[0].getType() == staff)
4068 rabbitkickragdoll = 1;
4070 if (animCurrent == rabbitkickreversedanim) {
4076 skeleton.spinny = 0;
4077 SolidHitBonus(!id); // FIXME: tricky id
4081 animTarget = rollanim;
4084 pause_sound(whooshsound);
4088 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4092 skeleton.spinny = 0;
4094 if (animCurrent == jumpreversedanim) {
4100 skeleton.spinny = 0;
4101 SolidHitBonus(!id); // FIXME: tricky id
4105 animTarget = rollanim;
4106 coords += facing * 2;
4108 pause_sound(whooshsound);
4113 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) {
4114 animTarget = getupfromfrontanim;
4116 } else if (Animation::animations[animCurrent].attack == normalattack) {
4117 animTarget = getIdle();
4120 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4121 animTarget = blockhighleftstrikeanim;
4123 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4124 animTarget = getIdle();
4127 if (animCurrent == spinkickanim && victim->skeleton.free) {
4128 if (creature == rabbittype)
4129 animTarget = fightidleanim;
4134 if (isIdle() && !wasIdle())
4135 normalsupdatedelay = 0;
4137 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4138 animTarget = jumpdownanim;
4141 if (!skeleton.free) {
4143 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4144 if (!isRun() || !wasRun()) {
4145 if (targetFrame().speed > currentFrame().speed)
4146 target += multiplier * targetFrame().speed * speed * 2;
4147 if (targetFrame().speed <= currentFrame().speed)
4148 target += multiplier * currentFrame().speed * speed * 2;
4150 if (isRun() && wasRun()) {
4152 tempspeed = velspeed;
4153 if (tempspeed < 10 * speedmult)
4154 tempspeed = 10 * speedmult;
4155 /* FIXME - mixed of target and current here, is that intended? */
4156 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4158 } else if (transspeed)
4159 target += multiplier * transspeed * speed * 2;
4161 if (!isRun() || !wasRun()) {
4162 if (targetFrame().speed > currentFrame().speed)
4163 target += multiplier * targetFrame().speed * 2;
4164 if (targetFrame().speed <= currentFrame().speed)
4165 target += multiplier * currentFrame().speed * 2;
4169 if (animCurrent != animTarget)
4170 target = (target + oldtarget) / 2;
4173 frameCurrent = frameTarget;
4177 rot = targetrot * target;
4178 yaw += rot - oldrot;
4184 if (frameCurrent >= Animation::animations[animCurrent].frames.size()) {
4185 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4187 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4189 for (int i = 0; i < skeleton.joints.size(); i++) {
4190 skeleton.joints[i].position = currentFrame().joints[i].position;
4193 skeleton.FindForwards();
4195 for (int i = 0; i < skeleton.muscles.size(); i++) {
4196 if (skeleton.muscles[i].visible) {
4197 skeleton.FindRotationMuscle(i, animTarget);
4200 for (int i = 0; i < skeleton.muscles.size(); i++) {
4201 if (skeleton.muscles[i].visible) {
4202 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4203 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4204 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4205 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4206 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4207 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4212 for (int i = 0; i < skeleton.joints.size(); i++) {
4213 skeleton.joints[i].position = targetFrame().joints[i].position;
4216 skeleton.FindForwards();
4218 for (int i = 0; i < skeleton.muscles.size(); i++) {
4219 if (skeleton.muscles[i].visible) {
4220 skeleton.FindRotationMuscle(i, animTarget);
4223 for (int i = 0; i < skeleton.muscles.size(); i++) {
4224 if (skeleton.muscles[i].visible) {
4225 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4226 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4227 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4228 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4229 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4230 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4231 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4232 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4233 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4234 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4235 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4236 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4241 oldanimCurrent = animCurrent;
4242 oldanimTarget = animTarget;
4243 oldframeTarget = frameTarget;
4244 oldframeCurrent = frameCurrent;
4246 for (int i = 0; i < skeleton.joints.size(); i++) {
4247 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4248 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4250 offset = currentoffset * (1 - target) + targetoffset * target;
4251 for (int i = 0; i < skeleton.muscles.size(); i++) {
4252 if (skeleton.muscles[i].visible) {
4253 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4254 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4255 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4260 if (isLanding() && landhard) {
4263 animTarget = getLandhard();
4276 void Person::DoStuff()
4278 static XYZ terrainnormal;
4279 static XYZ flatfacing;
4280 static XYZ flatvelocity;
4281 static float flatvelspeed;
4285 static int bloodsize;
4286 static int startx, starty, endx, endy;
4287 static GLubyte color;
4288 static XYZ bloodvel;
4290 onfiredelay -= multiplier;
4291 if (onfiredelay < 0 && onfire) {
4292 if (Random() % 2 == 0) {
4298 crouchkeydowntime += multiplier;
4300 crouchkeydowntime = 0;
4301 jumpkeydowntime += multiplier;
4302 if (!jumpkeydown && skeleton.free)
4303 jumpkeydowntime = 0;
4305 if (hostile || damage > 0 || bloodloss > 0)
4308 if (isIdle() || isRun())
4311 if (num_weapons == 1 && weaponactive != -1)
4315 blooddimamount -= multiplier * .3;
4316 speechdelay -= multiplier;
4317 texupdatedelay -= multiplier;
4318 interestdelay -= multiplier;
4319 flamedelay -= multiplier;
4320 parriedrecently -= multiplier;
4322 victim = this->shared_from_this();
4327 speed = 1.1 * speedmult;
4329 speed = 1.0 * speedmult;
4331 rabbitkickragdoll = 0;
4335 if (id != 0 && (creature == rabbittype || difficulty != 2))
4337 if (id != 0 && creature == wolftype && difficulty == 2) {
4339 if (aitype != passivetype) {
4341 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) {
4347 if (animTarget == wolfrunninganim && !superruntoggle) {
4348 animTarget = getRun();
4352 if (weaponactive == -1 && num_weapons > 0) {
4353 if (weapons[weaponids[0]].getType() == staff) {
4359 burnt += multiplier;
4363 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4365 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4371 vel[0] = velocity.x;
4372 vel[1] = velocity.y;
4373 vel[2] = velocity.z;
4376 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4377 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4381 while (flamedelay < 0 && onfire) {
4383 howmany = abs(Random() % (skeleton.joints.size()));
4384 if (skeleton.free) {
4385 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4386 flatfacing = skeleton.joints[howmany].position * scale + coords;
4388 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4389 flatvelocity = (coords - oldcoords) / multiplier / 2;
4391 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4394 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4396 howmany = abs(Random() % (skeleton.joints.size()));
4397 if (skeleton.free) {
4398 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4399 flatfacing = skeleton.joints[howmany].position * scale + coords;
4401 flatvelocity = (coords - oldcoords) / multiplier / 2;
4402 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4404 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4408 bleeding -= multiplier * .3;
4409 if (bloodtoggle == 2) {
4410 skeleton.drawmodel.textureptr.bind();
4411 if ((bleeding <= 0) && (detail != 2))
4416 if (neckspurtamount > 0) {
4417 neckspurtamount -= multiplier;
4418 neckspurtdelay -= multiplier * 3;
4419 neckspurtparticledelay -= multiplier * 3;
4420 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4423 if (skeleton.free) {
4424 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4425 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4426 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4428 bloodvel.z = 5 * neckspurtamount;
4429 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4430 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4431 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4433 neckspurtparticledelay = .05;
4435 if (neckspurtdelay < 0) {
4440 if (deathbleeding > 0 && dead != 2) {
4441 if (deathbleeding < 5)
4442 bleeddelay -= deathbleeding * multiplier / 4;
4444 bleeddelay -= 5 * multiplier / 4;
4445 if (bleeddelay < 0 && bloodtoggle) {
4450 if (skeleton.free) {
4451 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4452 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4454 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4455 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4459 bloodloss += deathbleeding * multiplier * 80;
4460 deathbleeding -= multiplier * 1.6;
4461 if (deathbleeding < 0)
4463 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4464 if (weaponactive != -1) {
4465 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4466 weapons[weaponids[0]].velocity.x += .01;
4469 weaponids[0] = weaponids[num_weapons];
4470 if (weaponstuck == num_weapons)
4474 for (unsigned i = 0; i < Person::players.size(); i++) {
4475 Person::players[i]->wentforweapon = 0;
4483 if (!dead && creature == wolftype) {
4484 award_bonus(0, Wolfbonus);
4487 if (animTarget == knifefollowedanim && !skeleton.free) {
4488 for (int i = 0; i < skeleton.joints.size(); i++) {
4489 skeleton.joints[i].velocity = 0;
4490 skeleton.joints[i].velocity.y = -2;
4493 if (id != 0 && unconscioustime > .1) {
4501 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4502 texupdatedelay = .12;
4504 bloodsize = 5 - realtexdetail;
4508 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4509 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4510 endx = startx + bloodsize;
4511 endy = starty + bloodsize;
4521 if (endx > skeleton.skinsize - 1) {
4522 endx = skeleton.skinsize - 1;
4525 if (endy > skeleton.skinsize - 1) {
4526 endy = skeleton.skinsize - 1;
4534 for (i = startx; i < endx; i++) {
4535 for (j = starty; j < endy; j++) {
4536 if (Random() % 2 == 0) {
4537 color = Random() % 85 + 170;
4538 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4539 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4540 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4541 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4546 skeleton.drawmodel.textureptr.bind();
4550 if (skeleton.free) {
4551 bleedx += 4 * direction / realtexdetail;
4553 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4555 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4557 bleedy -= 4 / realtexdetail;
4559 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4561 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4565 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4566 righthandmorphness = targetrighthandmorphness;
4567 righthandmorphstart = righthandmorphend;
4568 } else if (righthandmorphness > targetrighthandmorphness) {
4569 righthandmorphness -= multiplier * 4;
4570 } else if (righthandmorphness < targetrighthandmorphness) {
4571 righthandmorphness += multiplier * 4;
4574 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4575 lefthandmorphness = targetlefthandmorphness;
4576 lefthandmorphstart = lefthandmorphend;
4577 } else if (lefthandmorphness > targetlefthandmorphness) {
4578 lefthandmorphness -= multiplier * 4;
4579 } else if (lefthandmorphness < targetlefthandmorphness) {
4580 lefthandmorphness += multiplier * 4;
4583 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4584 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4585 tailmorphness = targettailmorphness;
4586 tailmorphstart = tailmorphend;
4587 } else if (tailmorphness > targettailmorphness) {
4588 tailmorphness -= multiplier * 10;
4589 } else if (tailmorphness < targettailmorphness) {
4590 tailmorphness += multiplier * 10;
4594 if (creature == wolftype) {
4595 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4596 tailmorphness = targettailmorphness;
4597 tailmorphstart = tailmorphend;
4598 } else if (tailmorphness > targettailmorphness) {
4599 tailmorphness -= multiplier * 2;
4600 } else if (tailmorphness < targettailmorphness) {
4601 tailmorphness += multiplier * 2;
4605 if (headmorphend == 3 || headmorphstart == 3) {
4606 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4607 headmorphness = targetheadmorphness;
4608 headmorphstart = headmorphend;
4609 } else if (headmorphness > targetheadmorphness) {
4610 headmorphness -= multiplier * 7;
4611 } else if (headmorphness < targetheadmorphness) {
4612 headmorphness += multiplier * 7;
4614 } else if (headmorphend == 5 || headmorphstart == 5) {
4615 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4616 headmorphness = targetheadmorphness;
4617 headmorphstart = headmorphend;
4618 } else if (headmorphness > targetheadmorphness) {
4619 headmorphness -= multiplier * 10;
4620 } else if (headmorphness < targetheadmorphness) {
4621 headmorphness += multiplier * 10;
4624 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4625 headmorphness = targetheadmorphness;
4626 headmorphstart = headmorphend;
4627 } else if (headmorphness > targetheadmorphness) {
4628 headmorphness -= multiplier * 4;
4629 } else if (headmorphness < targetheadmorphness) {
4630 headmorphness += multiplier * 4;
4634 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4635 chestmorphness = targetchestmorphness;
4636 chestmorphstart = chestmorphend;
4637 } else if (chestmorphness > targetchestmorphness) {
4638 chestmorphness -= multiplier;
4639 } else if (chestmorphness < targetchestmorphness) {
4640 chestmorphness += multiplier;
4643 if (dead != 2 && howactive <= typesleeping) {
4644 if (chestmorphstart == 0 && chestmorphend == 0) {
4646 targetchestmorphness = 1;
4649 if (chestmorphstart != 0 && chestmorphend != 0) {
4651 targetchestmorphness = 1;
4653 if (environment == snowyenvironment) {
4656 if (skeleton.free) {
4657 footvel = skeleton.specialforward[0] * -1;
4658 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4660 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4661 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4663 if (animTarget == sleepanim)
4664 footvel = DoRotation(footvel, 0, 90, 0);
4665 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4669 if (!dead && howactive < typesleeping) {
4670 blinkdelay -= multiplier * 2;
4671 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4673 targetheadmorphness = 1;
4675 blinkdelay = (float)(abs(Random() % 40)) / 5;
4677 if (headmorphstart == 3 && headmorphend == 3) {
4679 targetheadmorphness = 1;
4684 twitchdelay -= multiplier * 1.5;
4685 if (animTarget != hurtidleanim) {
4686 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4688 targetheadmorphness = 1;
4690 twitchdelay = (float)(abs(Random() % 40)) / 5;
4692 if (headmorphstart == 5 && headmorphend == 5) {
4694 targetheadmorphness = 1;
4698 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4699 twitchdelay3 -= multiplier * 1;
4700 if (Random() % 2 == 0) {
4701 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4702 righthandmorphness = 0;
4703 targetrighthandmorphness = 1;
4704 righthandmorphend = 1;
4705 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4707 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4708 righthandmorphness = 0;
4709 targetrighthandmorphness = 1;
4710 righthandmorphend = 0;
4713 if (Random() % 2 == 0) {
4714 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4715 lefthandmorphness = 0;
4716 targetlefthandmorphness = 1;
4717 lefthandmorphend = 1;
4718 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4720 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4721 lefthandmorphness = 0;
4722 targetlefthandmorphness = 1;
4723 lefthandmorphend = 0;
4729 if (creature == rabbittype) {
4730 if (howactive < typesleeping)
4731 twitchdelay2 -= multiplier * 1.5;
4733 twitchdelay2 -= multiplier * 0.5;
4734 if (howactive <= typesleeping) {
4735 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4737 targettailmorphness = 1;
4739 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4741 if (tailmorphstart == 1 && tailmorphend == 1) {
4743 targettailmorphness = 1;
4746 if (tailmorphstart == 2 && tailmorphend == 2) {
4748 targettailmorphness = 1;
4755 if (creature == wolftype) {
4756 twitchdelay2 -= multiplier * 1.5;
4757 if (tailmorphend != 0)
4758 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4760 targettailmorphness = 1;
4764 if (tailmorphend != 5)
4765 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4767 targettailmorphness = 1;
4771 if (twitchdelay2 <= 0) {
4772 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4774 targettailmorphness = 1;
4777 if (tailmorphstart == 1 && tailmorphend == 1) {
4779 targettailmorphness = 1;
4782 if (tailmorphstart == 2 && tailmorphend == 2) {
4784 targettailmorphness = 1;
4787 if (tailmorphstart == 3 && tailmorphend == 3) {
4789 targettailmorphness = 1;
4792 if (tailmorphstart == 4 && tailmorphend == 4) {
4794 targettailmorphness = 1;
4801 unconscioustime = 0;
4803 if (dead == 1 || howactive == typesleeping) {
4804 unconscioustime += multiplier;
4805 //If unconscious, close eyes and mouth
4806 if (righthandmorphend != 0)
4807 righthandmorphness = 0;
4808 righthandmorphend = 0;
4809 targetrighthandmorphness = 1;
4811 if (lefthandmorphend != 0)
4812 lefthandmorphness = 0;
4813 lefthandmorphend = 0;
4814 targetlefthandmorphness = 1;
4816 if (headmorphend != 3 && headmorphend != 5)
4819 targetheadmorphness = 1;
4823 if (howactive > typesleeping) {
4826 if (bloodtoggle && !bled) {
4827 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4829 if (bloodtoggle && !bled)
4830 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4831 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4832 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4836 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4841 if (dead == 2 || howactive > typesleeping) {
4842 //If dead, open mouth and hands
4843 if (righthandmorphend != 0)
4844 righthandmorphness = 0;
4845 righthandmorphend = 0;
4846 targetrighthandmorphness = 1;
4848 if (lefthandmorphend != 0)
4849 lefthandmorphness = 0;
4850 lefthandmorphend = 0;
4851 targetlefthandmorphness = 1;
4853 if (headmorphend != 2)
4856 targetheadmorphness = 1;
4859 if (stunned > 0 && !dead && headmorphend != 2) {
4860 if (headmorphend != 4)
4863 targetheadmorphness = 1;
4866 if (damage > damagetolerance && !dead) {
4869 unconscioustime = 0;
4871 if (creature == wolftype) {
4872 award_bonus(0, Wolfbonus);
4877 if (weaponactive != -1) {
4878 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4879 weapons[weaponids[0]].velocity.x += .01;
4882 weaponids[0] = weaponids[num_weapons];
4883 if (weaponstuck == num_weapons)
4887 for (unsigned i = 0; i < Person::players.size(); i++) {
4888 Person::players[i]->wentforweapon = 0;
4894 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4903 damage -= multiplier * 13;
4905 permanentdamage -= multiplier * 4;
4906 if (isIdle() || isCrouch()) {
4908 permanentdamage -= multiplier * 4;
4912 if (permanentdamage < 0)
4913 permanentdamage = 0;
4914 if (superpermanentdamage < 0)
4915 superpermanentdamage = 0;
4916 if (permanentdamage < superpermanentdamage) {
4917 permanentdamage = superpermanentdamage;
4919 if (damage < permanentdamage) {
4920 damage = permanentdamage;
4922 if (dead == 1 && damage < damagetolerance) {
4926 for (int i = 0; i < skeleton.joints.size(); i++) {
4927 skeleton.joints[i].velocity = 0;
4930 if (permanentdamage > damagetolerance && dead != 2) {
4933 if (weaponactive != -1) {
4934 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4935 weapons[weaponids[0]].velocity.x += .01;
4938 weaponids[0] = weaponids[num_weapons];
4939 if (weaponstuck == num_weapons)
4943 for (unsigned i = 0; i < Person::players.size(); i++) {
4944 Person::players[i]->wentforweapon = 0;
4950 if (!dead && creature == wolftype) {
4951 award_bonus(0, Wolfbonus);
4954 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4955 award_bonus(id, touchofdeath);
4956 if (id != 0 && unconscioustime > .1) {
4964 emit_sound_at(breaksound, coords);
4967 if (skeleton.free == 1) {
4969 pause_sound(whooshsound);
4972 //If knocked over, open hands and close mouth
4973 if (righthandmorphend != 0)
4974 righthandmorphness = 0;
4975 righthandmorphend = 0;
4976 targetrighthandmorphness = 1;
4978 if (lefthandmorphend != 0)
4979 lefthandmorphness = 0;
4980 lefthandmorphend = 0;
4981 targetlefthandmorphness = 1;
4983 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4984 if (headmorphend != 0)
4987 targetheadmorphness = 1;
4991 skeleton.DoGravity(&scale);
4993 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4994 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4995 award_bonus(id, deepimpact);
4996 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5000 for (j = 0; j < skeleton.joints.size(); j++) {
5001 average += skeleton.joints[j].position;
5005 coords += average * scale;
5006 for (j = 0; j < skeleton.joints.size(); j++) {
5007 skeleton.joints[j].position -= average;
5009 average /= multiplier;
5012 for (int i = 0; i < skeleton.joints.size(); i++) {
5013 velocity += skeleton.joints[i].velocity * scale;
5015 velocity /= skeleton.joints.size();
5017 if (!isnormal(velocity.x) && velocity.x) {
5021 if (findLength(&average) < 10 && dead && skeleton.free) {
5022 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5023 if (skeleton.longdead > 2000) {
5024 if (skeleton.longdead > 6000) {
5026 pause_sound(whooshsound);
5031 if (dead == 2 && bloodloss < damagetolerance) {
5033 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5035 if (bloodtoggle && !bled) {
5036 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5038 if (bloodtoggle && !bled)
5039 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5040 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5041 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5042 float size = .2 * 1.2;
5045 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5049 if (dead == 2 && bloodloss >= damagetolerance) {
5051 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5054 if (bloodtoggle && !bled) {
5055 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5057 if (bloodtoggle && !bled)
5058 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5059 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5060 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5064 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5071 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5072 bool canrecover = 1;
5073 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5074 startpoint = coords;
5077 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5079 if (velocity.y < -30)
5081 for (i = 0; i < objects.numobjects; i++) {
5082 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5083 colviewer = startpoint;
5084 coltarget = endpoint;
5085 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5094 terrainnormal = jointPos(groin) - jointPos(abdomen);
5095 if (joint(groin).locked && joint(abdomen).locked) {
5096 terrainnormal = jointPos(groin) - jointPos(abdomen);
5097 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5099 if (joint(abdomen).locked && joint(neck).locked) {
5100 terrainnormal = jointPos(abdomen) - jointPos(neck);
5101 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5103 if (joint(groin).locked && joint(neck).locked) {
5104 terrainnormal = jointPos(groin) - jointPos(neck);
5105 middle = (jointPos(groin) + jointPos(neck)) / 2;
5107 Normalise(&terrainnormal);
5109 targetyaw = -asin(0 - terrainnormal.x);
5110 targetyaw *= 360 / 6.28;
5111 if (terrainnormal.z < 0)
5112 targetyaw = 180 - targetyaw;
5116 animTarget = flipanim;
5117 crouchtogglekeydown = 1;
5122 animCurrent = tempanim;
5126 for (int i = 0; i < skeleton.joints.size(); i++) {
5127 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5128 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5133 if (findLength(&average) < 10 && !dead && skeleton.free) {
5134 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5135 if (skeleton.longdead > (damage + 500) * 1.5) {
5137 pause_sound(whooshsound);
5143 terrainnormal = jointPos(groin) - jointPos(abdomen);
5144 if (joint(groin).locked && joint(abdomen).locked) {
5145 terrainnormal = jointPos(groin) - jointPos(abdomen);
5146 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5148 if (joint(abdomen).locked && joint(neck).locked) {
5149 terrainnormal = jointPos(abdomen) - jointPos(neck);
5150 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5152 if (joint(groin).locked && joint(neck).locked) {
5153 terrainnormal = jointPos(groin) - jointPos(neck);
5154 middle = (jointPos(groin) + jointPos(neck)) / 2;
5156 Normalise(&terrainnormal);
5158 targetyaw = -asin(0 - terrainnormal.x);
5159 targetyaw *= 360 / 6.28;
5160 if (terrainnormal.z < 0)
5161 targetyaw = 180 - targetyaw;
5164 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5167 if (skeleton.forward.y < 0) {
5168 animTarget = getupfrombackanim;
5172 if (skeleton.forward.y > -.3) {
5173 animTarget = getupfromfrontanim;
5181 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5182 animTarget = rollanim;
5183 targetyaw = lookyaw;
5200 if ( !leftkeydown && !rightkeydown)
5207 if (abs(targettilt2) > 50)
5209 animCurrent = tempanim;
5212 tilt2 = targettilt2;
5214 if (middle.y > 0 && animTarget != rollanim)
5215 targetoffset.y = middle.y + 1;
5217 for (int i = 0; i < skeleton.joints.size(); i++) {
5218 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5219 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5226 if (num_weapons > 0)
5227 if (weapons[0].getType() == staff)
5229 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5230 if (velocity.y > -30) {
5232 tempvelocity = velocity;
5233 Normalise(&tempvelocity);
5234 targetyaw = -asin(0 - tempvelocity.x);
5235 targetyaw *= 360 / 6.28;
5237 targetyaw = 180 - targetyaw;
5241 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5242 animTarget = rollanim;
5245 animTarget = backhandspringanim;
5251 emit_sound_at(movewhooshsound, coords, 128.);
5253 animCurrent = animTarget;
5254 frameCurrent = frameTarget - 1;
5266 if (skeleton.freefall == 0)
5271 if (aitype != passivetype || skeleton.free == 1)
5272 if (findLengthfast(&velocity) > .1)
5273 for (i = 0; i < objects.numobjects; i++) {
5274 if (objects.type[i] == firetype)
5275 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5277 if (!objects.onfire[i]) {
5278 emit_sound_at(firestartsound, objects.position[i]);
5280 objects.onfire[i] = 1;
5283 if (objects.onfire[i]) {
5288 if (objects.type[i] == bushtype)
5289 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5291 if (!objects.onfire[i]) {
5292 emit_sound_at(firestartsound, objects.position[i]);
5294 objects.onfire[i] = 1;
5298 if (objects.onfire[i]) {
5302 if (objects.messedwith[i] <= 0) {
5306 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5309 addEnvSound(coords, 4 * findLength(&velocity));
5313 if (environment == grassyenvironment)
5314 howmany = findLength(&velocity) * 4;
5315 if (environment == snowyenvironment)
5316 howmany = findLength(&velocity) * 2;
5318 if (environment != desertenvironment)
5319 for (j = 0; j < howmany; j++) {
5320 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5321 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5322 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5325 pos.x += float(abs(Random() % 100) - 50) / 200;
5326 pos.y += float(abs(Random() % 100) - 50) / 200;
5327 pos.z += float(abs(Random() % 100) - 50) / 200;
5328 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);
5329 Sprite::setLastSpriteSpecial(1);
5331 howmany = findLength(&velocity) * 4;
5333 if (environment == snowyenvironment)
5334 for (j = 0; j < howmany; j++) {
5335 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5336 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5337 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5340 pos.x += float(abs(Random() % 100) - 50) / 200;
5341 pos.y += float(abs(Random() % 100) - 50) / 200;
5342 pos.z += float(abs(Random() % 100) - 50) / 200;
5343 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5344 Sprite::setLastSpriteSpecial(2);
5347 objects.rotx[i] += velocity.x * multiplier * 6;
5348 objects.roty[i] += velocity.z * multiplier * 6;
5349 objects.messedwith[i] = .5;
5352 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5353 if (objects.pitch[i] == 0)
5356 tempcoord = coords - objects.position[i];
5357 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5358 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5359 tempcoord += objects.position[i];
5361 if (distsqflat(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 8 && distsq(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 300 && tempcoord.y > objects.position[i].y + 3 * objects.scale[i]) {
5362 if (objects.messedwith[i] <= 0) {
5366 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5369 addEnvSound(coords, 4 * findLength(&velocity));
5373 if (environment == grassyenvironment)
5374 howmany = findLength(&velocity) * 4;
5375 if (environment == snowyenvironment)
5376 howmany = findLength(&velocity) * 2;
5378 if (environment != desertenvironment)
5379 for (j = 0; j < howmany; j++) {
5380 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5381 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5382 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5384 pos += velocity * .1;
5386 pos.x += float(abs(Random() % 100) - 50) / 150;
5387 pos.y += float(abs(Random() % 100) - 50) / 150;
5388 pos.z += float(abs(Random() % 100) - 50) / 150;
5389 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);
5390 Sprite::setLastSpriteSpecial(1);
5392 howmany = findLength(&velocity) * 4;
5394 if (environment == snowyenvironment)
5395 for (j = 0; j < howmany; j++) {
5396 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5397 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5398 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5400 pos += velocity * .1;
5402 pos.x += float(abs(Random() % 100) - 50) / 150;
5403 pos.y += float(abs(Random() % 100) - 50) / 150;
5404 pos.z += float(abs(Random() % 100) - 50) / 150;
5405 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5406 Sprite::setLastSpriteSpecial(2);
5409 objects.messedwith[i] = .5;
5414 if (!skeleton.free) {
5417 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5420 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5422 if (tutoriallevel == 1 && id != 0)
5424 if (play && aitype != playercontrolled) {
5425 int whichsound = -1;
5426 i = abs(Random() % 4);
5427 if (speechdelay <= 0) {
5428 if (creature == rabbittype) {
5430 whichsound = rabbitchitter;
5432 whichsound = rabbitchitter2;
5434 if (creature == wolftype) {
5436 whichsound = growlsound;
5438 whichsound = growl2sound;
5443 if (whichsound != -1) {
5444 emit_sound_at(whichsound, coords);
5448 if (animTarget == staggerbackhighanim)
5450 if (animTarget == staggerbackhardanim)
5452 staggerdelay -= multiplier;
5453 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5455 if (velocity.y < -30 && animTarget == jumpdownanim)
5457 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5458 animTarget = getIdle();
5462 weaponmissdelay -= multiplier;
5463 highreversaldelay -= multiplier;
5464 lowreversaldelay -= multiplier;
5465 lastcollide -= multiplier;
5466 skiddelay -= multiplier;
5467 if (!isnormal(velocity.x) && velocity.x) {
5470 if (!isnormal(targettilt) && targettilt) {
5473 if (!isnormal(targettilt2) && targettilt2) {
5476 if (!isnormal(targetyaw) && targetyaw) {
5480 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5481 //open hands and close mouth
5482 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5483 righthandmorphness = 0;
5484 righthandmorphend = 0;
5485 targetrighthandmorphness = 1;
5488 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5489 lefthandmorphness = 0;
5490 lefthandmorphend = 0;
5491 targetlefthandmorphness = 1;
5494 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5497 targetheadmorphness = 1;
5501 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) {
5502 //open hands and mouth
5503 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5504 righthandmorphness = 0;
5505 righthandmorphend = 0;
5506 targetrighthandmorphness = 1;
5509 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5510 lefthandmorphness = 0;
5511 lefthandmorphend = 0;
5512 targetlefthandmorphness = 1;
5515 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5518 targetheadmorphness = 1;
5522 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5523 //close hands and mouth
5524 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5525 righthandmorphness = 0;
5526 righthandmorphend = 1;
5527 targetrighthandmorphness = 1;
5530 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5531 lefthandmorphness = 0;
5532 lefthandmorphend = 1;
5533 targetlefthandmorphness = 1;
5536 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5539 targetheadmorphness = 1;
5543 if (animTarget == spinkickanim || animTarget == staffspinhitreversalanim || animTarget == staffspinhitreversedanim || animTarget == staffhitreversalanim || animTarget == staffhitreversedanim || animTarget == hurtidleanim || animTarget == winduppunchanim || animTarget == swordslashreversalanim || animTarget == swordslashreversedanim || animTarget == knifeslashreversalanim || animTarget == knifeslashreversedanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == knifefollowedanim || animTarget == killanim || animTarget == dropkickanim || animTarget == upunchanim || animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim || animTarget == staffgroundsmashanim || animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == lowkickanim || animTarget == sweepreversedanim || animTarget == rabbitkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversalanim || animTarget == jumpreversedanim) {
5544 //close hands and yell
5545 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5546 righthandmorphness = 0;
5547 righthandmorphend = 1;
5548 targetrighthandmorphness = 1;
5551 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5552 lefthandmorphness = 0;
5553 lefthandmorphend = 1;
5554 targetlefthandmorphness = 1;
5557 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5560 targetheadmorphness = 1;
5567 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5568 (victim->aitype != searchtype) && (aitype != passivetype) &&
5569 (aitype != searchtype) && (victim->id < Person::players.size())) {
5570 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5574 if (!dead && animTarget != hurtidleanim)
5575 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5576 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5579 targetheadmorphness = 1;
5583 if (weaponactive != -1) {
5584 if (weapons[weaponids[weaponactive]].getType() != staff) {
5585 righthandmorphstart = 1;
5586 righthandmorphend = 1;
5588 if (weapons[weaponids[weaponactive]].getType() == staff) {
5589 righthandmorphstart = 2;
5590 righthandmorphend = 2;
5592 targetrighthandmorphness = 1;
5595 terrainnormal = terrain.getNormal(coords.x, coords.z);
5597 if (Animation::animations[animTarget].attack != reversal) {
5598 if (!isnormal(coords.x))
5606 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5607 facing = flatfacing;
5608 ReflectVector(&facing, terrainnormal);
5611 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5613 targettilt2 = -facing.y * 20;
5618 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5620 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5621 flatvelocity = velocity;
5623 flatvelspeed = findLength(&flatvelocity);
5624 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5625 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5630 if (targettilt > 25)
5632 if (targettilt < -25)
5636 if (targettilt2 > 45)
5638 if (targettilt2 < -45)
5640 if (abs(tilt2 - targettilt2) < multiplier * 400)
5641 tilt2 = targettilt2;
5642 else if (tilt2 > targettilt2) {
5643 tilt2 -= multiplier * 400;
5644 } else if (tilt2 < targettilt2) {
5645 tilt2 += multiplier * 400;
5647 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5654 if (!isnormal(targettilt) && targettilt) {
5657 if (!isnormal(targettilt2) && targettilt2) {
5662 if (animTarget == rabbittackleanim) {
5663 velocity += facing * multiplier * speed * 700 * scale;
5664 velspeed = findLength(&velocity);
5665 if (velspeed > speed * 65 * scale) {
5666 velocity /= velspeed;
5667 velspeed = speed * 65 * scale;
5668 velocity *= velspeed;
5670 velocity.y += gravity * multiplier * 20;
5671 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5672 velspeed = findLength(&velocity);
5673 velocity = flatfacing * velspeed;
5675 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5676 if (isRun() || animTarget == rabbitkickanim) {
5677 velocity += facing * multiplier * speed * 700 * scale;
5678 velspeed = findLength(&velocity);
5679 if (velspeed > speed * 45 * scale) {
5680 velocity /= velspeed;
5681 velspeed = speed * 45 * scale;
5682 velocity *= velspeed;
5684 velocity.y += gravity * multiplier * 20;
5685 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5686 velspeed = findLength(&velocity);
5687 if (velspeed < speed * 30 * scale)
5688 velspeed = speed * 30 * scale;
5689 velocity = flatfacing * velspeed;
5691 } else if (isRun()) {
5692 velocity += facing * multiplier * speed * 700 * scale;
5693 velspeed = findLength(&velocity);
5694 if (creature == rabbittype) {
5695 if (velspeed > speed * 55 * scale) {
5696 velocity /= velspeed;
5697 velspeed = speed * 55 * scale;
5698 velocity *= velspeed;
5701 if (creature == wolftype) {
5702 if (velspeed > speed * 75 * scale) {
5703 velocity /= velspeed;
5704 velspeed = speed * 75 * scale;
5705 velocity *= velspeed;
5708 velocity.y += gravity * multiplier * 20;
5709 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5710 velspeed = findLength(&velocity);
5711 velocity = flatfacing * velspeed;
5714 if (animTarget == rollanim && targetFrame().label != 6) {
5715 velocity += facing * multiplier * speed * 700 * scale;
5716 velspeed = findLength(&velocity);
5717 if (velspeed > speed * 45 * scale) {
5718 velocity /= velspeed;
5719 velspeed = speed * 45 * scale;
5720 velocity *= velspeed;
5722 velocity.y += gravity * multiplier * 20;
5723 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5724 velspeed = findLength(&velocity);
5725 velocity = flatfacing * velspeed;
5728 if (animTarget == sneakanim || animTarget == walkanim) {
5729 velocity += facing * multiplier * speed * 700 * scale;
5730 velspeed = findLength(&velocity);
5731 if (velspeed > speed * 12 * scale) {
5732 velocity /= velspeed;
5733 velspeed = speed * 12 * scale;
5734 velocity *= velspeed;
5736 velocity.y += gravity * multiplier * 20;
5737 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5738 velspeed = findLength(&velocity);
5739 velocity = flatfacing * velspeed;
5742 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5743 velocity += facing * multiplier * speed * 700 * scale;
5744 velspeed = findLength(&velocity);
5745 if (velspeed > speed * 2 * scale) {
5746 velocity /= velspeed;
5747 velspeed = speed * 2 * scale;
5748 velocity *= velspeed;
5750 velocity.y += gravity * multiplier * 20;
5751 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5752 velspeed = findLength(&velocity);
5753 velocity = flatfacing * velspeed;
5757 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5758 velocity -= facing * multiplier * speed * 700 * scale;
5759 velspeed = findLength(&velocity);
5760 if (velspeed > speed * 2 * scale) {
5761 velocity /= velspeed;
5762 velspeed = speed * 2 * 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 * -1;
5771 if (animTarget == fightsidestep) {
5772 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
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 = DoRotation(flatfacing * velspeed, 0, -90, 0);
5785 if (animTarget == staggerbackhighanim) {
5786 coords -= facing * multiplier * speed * 16 * scale;
5789 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5790 coords -= facing * multiplier * speed * 20 * scale;
5794 if (animTarget == backhandspringanim) {
5795 //coords-=facing*multiplier*50*scale;
5796 velocity += facing * multiplier * speed * 700 * scale * -1;
5797 velspeed = findLength(&velocity);
5798 if (velspeed > speed * 50 * scale) {
5799 velocity /= velspeed;
5800 velspeed = speed * 50 * scale;
5801 velocity *= velspeed;
5803 velocity.y += gravity * multiplier * 20;
5804 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5805 velspeed = findLength(&velocity);
5806 velocity = flatfacing * velspeed * -1;
5808 if (animTarget == dodgebackanim) {
5809 //coords-=facing*multiplier*50*scale;
5810 velocity += facing * multiplier * speed * 700 * scale * -1;
5811 velspeed = findLength(&velocity);
5812 if (velspeed > speed * 60 * scale) {
5813 velocity /= velspeed;
5814 velspeed = speed * 60 * scale;
5815 velocity *= velspeed;
5817 velocity.y += gravity * multiplier * 20;
5818 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5819 velspeed = findLength(&velocity);
5820 velocity = flatfacing * velspeed * -1;
5823 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5824 velspeed = findLength(&velocity);
5828 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5829 velocity.y += gravity * multiplier;
5832 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5833 coords += velocity * multiplier;
5835 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5836 if (isFlip() && targetFrame().label == 7)
5839 if (animTarget == jumpupanim) {
5841 animTarget = getIdle();
5848 pause_sound(whooshsound);
5849 OPENAL_SetVolume(channels[whooshsound], 0);
5852 if (animTarget == jumpdownanim || isFlip()) {
5853 if (isFlip())jumppower = -4;
5854 animTarget = getLanding();
5855 emit_sound_at(landsound, coords, 128.);
5858 addEnvSound(coords);
5863 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5864 coords.y += gravity * multiplier * 2;
5865 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5866 coords.y = terrain.getHeight(coords.x, coords.z);
5871 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)) {
5872 velspeed = findLength(&velocity);
5874 if (velspeed < multiplier * 300 * scale) {
5877 velocity -= velocity / velspeed * multiplier * 300 * scale;
5878 if (velspeed > 5 && (isLanding() || isLandhard())) {
5879 skiddingdelay += multiplier;
5880 if (skiddelay <= 0) {
5881 FootLand(leftfoot, .5);
5882 FootLand(rightfoot, .5);
5890 velspeed = findLength(&velocity);
5892 if (velspeed < multiplier * 600 * scale) {
5895 velocity -= velocity / velspeed * multiplier * 600 * scale;
5897 if (velspeed > 5 && (isLanding() || isLandhard())) {
5898 skiddingdelay += multiplier;
5899 if (skiddelay <= 0) {
5900 FootLand(leftfoot, .5);
5901 FootLand(rightfoot, .5);
5908 if (skiddingdelay < 0)
5909 skiddingdelay += multiplier;
5910 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5912 if (!onterrain || environment == grassyenvironment) {
5913 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5915 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5919 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5920 terrainnormal = victim->coords - coords;
5921 Normalise(&terrainnormal);
5922 targetyaw = -asin(0 - terrainnormal.x);
5923 targetyaw *= 360 / 6.28;
5924 if (terrainnormal.z < 0)
5925 targetyaw = 180 - targetyaw;
5926 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5929 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5930 targetyaw = victim->targetyaw;
5932 if (animTarget == rabbittacklinganim) {
5933 coords = victim->coords;
5936 skeleton.oldfree = skeleton.free;
5940 midterrain.x = terrain.size * terrain.scale / 2;
5941 midterrain.z = terrain.size * terrain.scale / 2;
5942 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5944 tempposit = coords - midterrain;
5946 Normalise(&tempposit);
5947 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5948 coords.x = tempposit.x + midterrain.x;
5949 coords.z = tempposit.z + midterrain.z;
5955 * inverse kinematics helper function
5957 void IKHelper(Person *p, float interp)
5959 XYZ point, change, change2;
5960 float heightleft, heightright;
5962 // TODO: implement localToWorld and worldToLocal
5963 // but keep in mind it won't be the same math if player is ragdolled or something
5964 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5965 // then comb through code for places where to use it
5967 // point = localToWorld(jointPos(leftfoot))
5968 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5969 // adjust height of foot
5970 heightleft = terrain.getHeight(point.x, point.z) + .04;
5971 point.y = heightleft;
5972 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5973 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5974 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5975 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5976 // move ankle along with foot
5977 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5978 // average knee pos between old and new pos
5979 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5981 // do same as above for right leg
5982 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5983 heightright = terrain.getHeight(point.x, point.z) + .04;
5984 point.y = heightright;
5985 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5986 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5987 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5988 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5989 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5991 // fix up skeleton now that we've moved body parts?
5992 p->skeleton.DoConstraints(&p->coords, &p->scale);
5999 int Person::DrawSkeleton()
6001 int oldplayerdetail;
6002 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6003 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6013 glAlphaFunc(GL_GREATER, 0.0001);
6015 float terrainheight;
6019 if (!isnormal(tilt))
6021 if (!isnormal(tilt2))
6023 oldplayerdetail = playerdetail;
6025 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6028 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6031 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6036 if (playerdetail != oldplayerdetail) {
6038 normalsupdatedelay = 0;
6040 static float updatedelaychange;
6041 static float morphness;
6042 static float framemult;
6044 skeleton.FindForwards();
6045 if (howactive == typesittingwall) {
6046 skeleton.specialforward[1] = 0;
6047 skeleton.specialforward[1].z = 1;
6053 static int weaponattachmuscle;
6054 static int weaponrotatemuscle;
6055 static XYZ weaponpoint;
6056 static int start, endthing;
6057 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6058 if (!isSleeping() && !isSitting()) {
6059 // TODO: give these meaningful names
6060 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6061 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6062 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6063 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6065 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6067 if (creature == wolftype)
6071 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6072 IKHelper(this, target);
6073 if (creature == wolftype)
6074 IKHelper(this, target);
6077 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6078 IKHelper(this, 1 - target);
6079 if (creature == wolftype)
6080 IKHelper(this, 1 - target);
6084 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()))
6087 targetheadyaw = -targetyaw;
6088 targetheadpitch = 0;
6089 if (Animation::animations[animTarget].attack == 3)
6090 targetheadyaw += 180;
6092 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6093 skeleton.drawmodel.vertex[i] = 0;
6094 skeleton.drawmodel.vertex[i].y = 999;
6096 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6097 skeleton.drawmodellow.vertex[i] = 0;
6098 skeleton.drawmodellow.vertex[i].y = 999;
6100 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6101 skeleton.drawmodelclothes.vertex[i] = 0;
6102 skeleton.drawmodelclothes.vertex[i].y = 999;
6104 for (int i = 0; i < skeleton.muscles.size(); i++) {
6105 // convenience renames
6106 const int p1 = skeleton.muscles[i].parent1->label;
6107 const int p2 = skeleton.muscles[i].parent2->label;
6109 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6114 if (p1 == righthand || p2 == righthand) {
6115 morphness = righthandmorphness;
6116 start = righthandmorphstart;
6117 endthing = righthandmorphend;
6119 if (p1 == lefthand || p2 == lefthand) {
6120 morphness = lefthandmorphness;
6121 start = lefthandmorphstart;
6122 endthing = lefthandmorphend;
6124 if (p1 == head || p2 == head) {
6125 morphness = headmorphness;
6126 start = headmorphstart;
6127 endthing = headmorphend;
6129 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6130 morphness = chestmorphness;
6131 start = chestmorphstart;
6132 endthing = chestmorphend;
6134 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6135 morphness = tailmorphness;
6136 start = tailmorphstart;
6137 endthing = tailmorphend;
6140 skeleton.FindRotationMuscle(i, animTarget);
6141 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6142 glMatrixMode(GL_MODELVIEW);
6146 glRotatef(tilt2, 1, 0, 0);
6148 glRotatef(tilt, 0, 0, 1);
6151 glTranslatef(mid.x, mid.y, mid.z);
6153 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6154 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6156 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6157 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6159 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6160 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6162 if (playerdetail || skeleton.free == 3) {
6163 for (j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6164 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6165 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6166 glMatrixMode(GL_MODELVIEW);
6168 if (p1 == abdomen || p2 == abdomen)
6169 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6170 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6171 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6172 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6173 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6174 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6175 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6176 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6177 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6178 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6179 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6180 if (p1 == head || p2 == head)
6181 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6182 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6183 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6184 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6185 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6186 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6187 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6191 if (!playerdetail || skeleton.free == 3) {
6192 for (j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6193 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6194 glMatrixMode(GL_MODELVIEW);
6196 if (p1 == abdomen || p2 == abdomen)
6197 glTranslatef(v0.x * proportionbody.x,
6198 v0.y * proportionbody.y,
6199 v0.z * proportionbody.z);
6200 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6201 glTranslatef(v0.x * proportionarms.x,
6202 v0.y * proportionarms.y,
6203 v0.z * proportionarms.z);
6204 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6205 glTranslatef(v0.x * proportionlegs.x,
6206 v0.y * proportionlegs.y,
6207 v0.z * proportionlegs.z);
6208 if (p1 == head || p2 == head)
6209 glTranslatef(v0.x * proportionhead.x,
6210 v0.y * proportionhead.y,
6211 v0.z * proportionhead.z);
6213 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6214 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6215 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6216 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6222 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6223 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6225 glMatrixMode(GL_MODELVIEW);
6229 glRotatef(tilt2, 1, 0, 0);
6231 glRotatef(tilt, 0, 0, 1);
6232 glTranslatef(mid.x, mid.y, mid.z);
6233 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6234 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6236 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6237 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6239 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6240 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6242 for (j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6243 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6244 glMatrixMode(GL_MODELVIEW);
6246 if (p1 == abdomen || p2 == abdomen)
6247 glTranslatef(v0.x * proportionbody.x,
6248 v0.y * proportionbody.y,
6249 v0.z * proportionbody.z);
6250 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6251 glTranslatef(v0.x * proportionarms.x,
6252 v0.y * proportionarms.y,
6253 v0.z * proportionarms.z);
6254 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6255 glTranslatef(v0.x * proportionlegs.x,
6256 v0.y * proportionlegs.y,
6257 v0.z * proportionlegs.z);
6258 if (p1 == head || p2 == head)
6259 glTranslatef(v0.x * proportionhead.x,
6260 v0.y * proportionhead.y,
6261 v0.z * proportionhead.z);
6262 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6263 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6264 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6265 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6270 updatedelay = 1 + (float)(Random() % 100) / 1000;
6272 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6273 normalsupdatedelay = 1;
6274 if (playerdetail || skeleton.free == 3)
6275 skeleton.drawmodel.CalculateNormals(0);
6276 if (!playerdetail || skeleton.free == 3)
6277 skeleton.drawmodellow.CalculateNormals(0);
6278 if (skeleton.clothes)
6279 skeleton.drawmodelclothes.CalculateNormals(0);
6281 if (playerdetail || skeleton.free == 3)
6282 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6283 if (!playerdetail || skeleton.free == 3)
6284 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6285 if (skeleton.clothes) {
6286 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6291 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6292 if (updatedelaychange > -realmultiplier * 30)
6293 updatedelaychange = -realmultiplier * 30;
6294 if (updatedelaychange > -framemult * 4)
6295 updatedelaychange = -framemult * 4;
6296 if (skeleton.free == 1)
6297 updatedelaychange *= 6;
6299 updatedelaychange *= 8;
6300 updatedelay += updatedelaychange;
6302 glMatrixMode(GL_MODELVIEW);
6304 glTranslatef(coords.x, coords.y - .02, coords.z);
6305 if (!skeleton.free) {
6306 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6307 glRotatef(yaw, 0, 1, 0);
6311 glColor4f(.4, 1, .4, 1);
6312 glDisable(GL_LIGHTING);
6313 glDisable(GL_TEXTURE_2D);
6316 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6317 XYZ &v0 = skeleton.drawmodel.vertex[i];
6318 glVertex3f(v0.x, v0.y, v0.z);
6324 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6325 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6326 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6327 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6328 glVertex3f(v0.x, v0.y, v0.z);
6329 glVertex3f(v1.x, v1.y, v1.z);
6330 glVertex3f(v1.x, v1.y, v1.z);
6331 glVertex3f(v2.x, v2.y, v2.z);
6332 glVertex3f(v2.x, v2.y, v2.z);
6333 glVertex3f(v0.x, v0.y, v0.z);
6339 terrainlight = terrain.getLighting(coords.x, coords.z);
6340 distance = distsq(&viewer, &coords);
6341 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6345 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6346 if (terrainheight < 1)
6348 if (terrainheight > 1.7)
6349 terrainheight = 1.7;
6351 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6352 glDisable(GL_BLEND);
6353 glAlphaFunc(GL_GREATER, 0.0001);
6354 glEnable(GL_TEXTURE_2D);
6356 glDisable(GL_TEXTURE_2D);
6357 glColor4f(.7, .35, 0, .5);
6359 glEnable(GL_LIGHTING);
6362 if (tutoriallevel && id != 0) {
6363 glColor4f(.7, .7, .7, 0.6);
6365 glEnable(GL_LIGHTING);
6367 if (canattack && cananger)
6368 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6369 glDisable(GL_TEXTURE_2D);
6370 glColor4f(1, 0, 0, 0.8);
6372 glMatrixMode(GL_TEXTURE);
6374 glTranslatef(0, -smoketex, 0);
6375 glTranslatef(-smoketex, 0, 0);
6379 if ((tutoriallevel && id != 0))
6380 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6382 skeleton.drawmodel.draw();
6385 if (!playerdetail) {
6386 if ((tutoriallevel && id != 0))
6387 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6389 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6392 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6393 if (tutoriallevel && id != 0) {
6395 glMatrixMode(GL_MODELVIEW);
6396 glEnable(GL_TEXTURE_2D);
6397 glColor4f(.7, .7, .7, 0.6);
6399 glEnable(GL_LIGHTING);
6401 if (canattack && cananger)
6402 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6403 glDisable(GL_TEXTURE_2D);
6404 glColor4f(1, 0, 0, 0.8);
6406 glMatrixMode(GL_TEXTURE);
6408 glTranslatef(0, -smoketex * .6, 0);
6409 glTranslatef(smoketex * .6, 0, 0);
6412 if ((tutoriallevel && id != 0))
6413 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6415 skeleton.drawmodel.draw();
6418 if (!playerdetail) {
6419 if ((tutoriallevel && id != 0))
6420 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6422 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6427 if (tutoriallevel && id != 0) {
6429 glMatrixMode(GL_MODELVIEW);
6430 glEnable(GL_TEXTURE_2D);
6432 if (skeleton.clothes) {
6436 skeleton.drawmodelclothes.draw();
6438 skeleton.drawmodelclothes.drawimmediate();
6444 if (num_weapons > 0) {
6445 for (k = 0; k < num_weapons; k++) {
6447 if (weaponactive == k) {
6448 if (weapons[i].getType() != staff) {
6449 for (j = 0; j < skeleton.muscles.size(); j++) {
6450 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6451 weaponattachmuscle = j;
6454 for (j = 0; j < skeleton.muscles.size(); j++) {
6455 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) {
6456 weaponrotatemuscle = j;
6459 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6460 if (creature == wolftype)
6461 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6463 if (weapons[i].getType() == staff) {
6464 for (j = 0; j < skeleton.muscles.size(); j++) {
6465 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6466 weaponattachmuscle = j;
6469 for (j = 0; j < skeleton.muscles.size(); j++) {
6470 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) {
6471 weaponrotatemuscle = j;
6474 //weaponpoint=jointPos(rightwrist);
6475 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6476 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6477 XYZ tempnormthing, vec1, vec2;
6478 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6479 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6480 CrossProduct(&vec1, &vec2, &tempnormthing);
6481 Normalise(&tempnormthing);
6482 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6483 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6486 if (weaponactive != k && weaponstuck != k) {
6487 if (weapons[i].getType() == knife)
6488 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6489 if (weapons[i].getType() == sword)
6490 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6491 if (weapons[i].getType() == staff)
6492 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6493 for (j = 0; j < skeleton.muscles.size(); j++) {
6494 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) {
6495 weaponrotatemuscle = j;
6499 if (weaponstuck == k) {
6500 if (weaponstuckwhere == 0)
6501 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6503 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6504 for (j = 0; j < skeleton.muscles.size(); j++) {
6505 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) {
6506 weaponrotatemuscle = j;
6510 if (skeleton.free) {
6511 weapons[i].position = weaponpoint * scale + coords;
6512 weapons[i].bigrotation = 0;
6513 weapons[i].bigtilt = 0;
6514 weapons[i].bigtilt2 = 0;
6516 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;
6517 weapons[i].bigrotation = yaw;
6518 weapons[i].bigtilt = tilt;
6519 weapons[i].bigtilt2 = tilt2;
6521 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6522 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6523 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6524 if (weaponactive == k) {
6525 if (weapons[i].getType() == knife) {
6526 weapons[i].smallrotation = 180;
6527 weapons[i].smallrotation2 = 0;
6528 if (isCrouch() || wasCrouch()) {
6529 weapons[i].smallrotation2 = 20;
6531 if (animTarget == hurtidleanim) {
6532 weapons[i].smallrotation2 = 50;
6534 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6535 XYZ temppoint1, temppoint2;
6538 temppoint1 = jointPos(righthand);
6539 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6540 distance = findDistance(&temppoint1, &temppoint2);
6541 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6542 weapons[i].rotation2 *= 360 / 6.28;
6545 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6546 weapons[i].rotation1 *= 360 / 6.28;
6547 weapons[i].rotation3 = 0;
6548 weapons[i].smallrotation = -90;
6549 weapons[i].smallrotation2 = 0;
6550 if (temppoint1.x > temppoint2.x)
6551 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6553 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6554 XYZ temppoint1, temppoint2;
6557 temppoint1 = jointPos(righthand);
6558 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6559 distance = findDistance(&temppoint1, &temppoint2);
6560 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6561 weapons[i].rotation2 *= 360 / 6.28;
6564 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6565 weapons[i].rotation1 *= 360 / 6.28;
6566 weapons[i].rotation3 = 0;
6567 weapons[i].smallrotation = 90;
6568 weapons[i].smallrotation2 = 0;
6569 if (temppoint1.x > temppoint2.x)
6570 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6572 if (animTarget == knifethrowanim) {
6573 weapons[i].smallrotation = 90;
6574 //weapons[i].smallrotation2=-90;
6575 weapons[i].smallrotation2 = 0;
6576 weapons[i].rotation1 = 0;
6577 weapons[i].rotation2 = 0;
6578 weapons[i].rotation3 = 0;
6580 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6581 weapons[i].smallrotation = -90;
6582 weapons[i].rotation1 = 0;
6583 weapons[i].rotation2 = 0;
6584 weapons[i].rotation3 = 0;
6587 if (weapons[i].getType() == sword) {
6588 weapons[i].smallrotation = 0;
6589 weapons[i].smallrotation2 = 0;
6590 if (animTarget == knifethrowanim) {
6591 weapons[i].smallrotation = -90;
6592 weapons[i].smallrotation2 = 0;
6593 weapons[i].rotation1 = 0;
6594 weapons[i].rotation2 = 0;
6595 weapons[i].rotation3 = 0;
6597 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)) {
6598 XYZ temppoint1, temppoint2;
6601 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6602 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6603 distance = findDistance(&temppoint1, &temppoint2);
6604 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6605 weapons[i].rotation2 *= 360 / 6.28;
6608 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6609 weapons[i].rotation1 *= 360 / 6.28;
6610 weapons[i].rotation3 = 0;
6611 weapons[i].smallrotation = 90;
6612 weapons[i].smallrotation2 = 0;
6613 if (temppoint1.x > temppoint2.x)
6614 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6617 if (weapons[i].getType() == staff) {
6618 weapons[i].smallrotation = 100;
6619 weapons[i].smallrotation2 = 0;
6620 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6621 XYZ temppoint1, temppoint2;
6624 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6625 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6626 distance = findDistance(&temppoint1, &temppoint2);
6627 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6628 weapons[i].rotation2 *= 360 / 6.28;
6631 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6632 weapons[i].rotation1 *= 360 / 6.28;
6633 weapons[i].rotation3 = 0;
6634 weapons[i].smallrotation = 90;
6635 weapons[i].smallrotation2 = 0;
6636 if (temppoint1.x > temppoint2.x)
6637 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6641 if (weaponactive != k && weaponstuck != k) {
6642 if (weapons[i].getType() == knife) {
6643 weapons[i].smallrotation = -70;
6644 weapons[i].smallrotation2 = 10;
6646 if (weapons[i].getType() == sword) {
6647 weapons[i].smallrotation = -100;
6648 weapons[i].smallrotation2 = -8;
6650 if (weapons[i].getType() == staff) {
6651 weapons[i].smallrotation = -100;
6652 weapons[i].smallrotation2 = -8;
6655 if (weaponstuck == k) {
6656 if (weaponstuckwhere == 0)
6657 weapons[i].smallrotation = 180;
6659 weapons[i].smallrotation = 0;
6660 weapons[i].smallrotation2 = 10;
6669 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6671 if (animCurrent != animTarget)
6673 if (skeleton.free == 2)
6682 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6685 static float distance;
6686 static float olddistance;
6687 static int intersecting;
6688 static int firstintersecting;
6691 static XYZ start, end;
6692 static float slopethreshold = -.4;
6694 firstintersecting = -1;
6698 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6701 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6702 for (i = 0; i < 4; i++) {
6703 for (j = 0; j < model->TriangleNum; j++) {
6704 if (model->facenormals[j].y <= slopethreshold) {
6706 distance = abs((model->facenormals[j].x * p1->x) + (model->facenormals[j].y * p1->y) + (model->facenormals[j].z * p1->z) - ((model->facenormals[j].x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->facenormals[j].y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->facenormals[j].z * model->vertex[model->Triangles[j].vertex[0]].z)));
6707 if (distance < radius) {
6708 point = *p1 - model->facenormals[j] * distance;
6709 if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))
6712 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6713 &model->vertex[model->Triangles[j].vertex[1]],
6716 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6717 &model->vertex[model->Triangles[j].vertex[2]],
6720 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6721 &model->vertex[model->Triangles[j].vertex[2]],
6724 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6728 if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->facenormals[j], &point)) {
6729 p1->y = point.y + radius;
6730 if ((animTarget == jumpdownanim || isFlip())) {
6731 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6734 if (animTarget == jumpupanim) {
6736 animTarget = getIdle();
6743 pause_sound(whooshsound);
6744 OPENAL_SetVolume(channels[whooshsound], 0);
6747 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6750 animTarget = getLanding();
6751 emit_sound_at(landsound, coords, 128.);
6754 addEnvSound(coords);
6761 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6762 olddistance = distance;
6763 firstintersecting = j;
6768 for (j = 0; j < model->TriangleNum; j++) {
6769 if (model->facenormals[j].y > slopethreshold) {
6772 start.y -= radius / 4;
6773 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6774 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6775 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6776 distance = abs((model->facenormals[j].x * start.x)
6777 + (model->facenormals[j].y * start.y)
6778 + (model->facenormals[j].z * start.z)
6779 - ((model->facenormals[j].x * v0.x)
6780 + (model->facenormals[j].y * v0.y)
6781 + (model->facenormals[j].z * v0.z)));
6782 if (distance < radius * .5) {
6783 point = start - model->facenormals[j] * distance;
6784 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6787 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6789 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6791 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6793 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6794 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6796 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6797 if (findLengthfast(&start) < findLengthfast(&velocity))
6800 *p1 += model->facenormals[j] * (distance - radius * .5);
6803 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6804 olddistance = distance;
6805 firstintersecting = j;
6812 *p = DoRotation(*p, 0, *rotate, 0);
6815 *p1 = DoRotation(*p1, 0, *rotate, 0);
6817 return firstintersecting;
6820 void Person::takeWeapon(int weaponId)
6823 weapons[weaponId].owner = id;
6824 if (num_weapons > 0) {
6825 weaponids[num_weapons] = weaponids[0];
6828 weaponids[0] = weaponId;
6831 void Person::addClothes()
6833 if (numclothes > 0) {
6834 for (int i = 0; i < numclothes; i++) {
6841 bool Person::addClothes(const int& clothesId)
6844 const std::string fileName = clothes[clothesId];
6846 GLubyte* array = &skeleton.skinText[0];
6850 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6855 float tintr = clothestintr[clothesId];
6856 float tintg = clothestintg[clothesId];
6857 float tintb = clothestintb[clothesId];
6859 if (tintr > 1) tintr = 1;
6860 if (tintg > 1) tintg = 1;
6861 if (tintb > 1) tintb = 1;
6863 if (tintr < 0) tintr = 0;
6864 if (tintg < 0) tintg = 0;
6865 if (tintb < 0) tintb = 0;
6867 int bytesPerPixel = texture.bpp / 8;
6871 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6872 if (bytesPerPixel == 3)
6874 else if ((i + 1) % 4 == 0)
6875 alphanum = texture.data[i];
6876 if ((i + 1) % 4 || bytesPerPixel == 3) {
6878 texture.data[i] *= tintr;
6880 texture.data[i] *= tintg;
6882 texture.data[i] *= tintb;
6883 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);