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.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[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.num_joints; 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/doDebugKeys - 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.num_joints));
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[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.num_joints; 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.num_muscles; 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.num_joints; 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.num_joints; i++) {
1735 skeleton.joints[i].velocity = 0;
1736 skeleton.joints[i].velchange = 0;
1738 skeleton.DoConstraints(&coords, &scale);
1739 if (animation[animCurrent].height == lowheight || animation[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 = animation[animTarget].speed[frameTarget] * 2;
1747 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1748 speed = animation[animCurrent].speed[frameCurrent] * 2;
1751 speed = transspeed * 2;
1755 for (int i = 0; i < skeleton.num_joints; i++) {
1756 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1757 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((animation[animTarget].position[i][frameTarget] - animation[animCurrent].position[i][frameCurrent]) * 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.num_joints)].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.num_joints)].velchange -= change;
1773 if (checkcollision) {
1780 for (j = 0; j < skeleton.num_joints; j++) {
1781 average += skeleton.joints[j].position;
1785 coords += average * scale;
1786 for (j = 0; j < skeleton.num_joints; 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.num_joints; i++) {
1809 velocity += skeleton.joints[i].velocity * scale;
1811 velocity /= skeleton.num_joints;
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(bodyparts 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[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[animTarget].attack != reversed)
1967 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1968 crouchtogglekeydown = 0;
1969 if (aitype == playercontrolled)
1972 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1975 crouchtogglekeydown = 1;
1979 if (animation[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) && (animation[animTarget].label[frameTarget] || (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 ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2039 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2040 if (animation[animTarget].label[frameTarget] == 1)
2041 whichsound = footstepsound;
2043 whichsound = footstepsound2;
2044 if (animation[animTarget].label[frameTarget] == 1)
2045 FootLand(leftfoot, 1);
2046 if (animation[animTarget].label[frameTarget] == 2)
2047 FootLand(rightfoot, 1);
2048 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
2049 FootLand(rightfoot, 1);
2050 FootLand(leftfoot, 1);
2054 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2055 if (animation[animTarget].label[frameTarget] == 1)
2056 whichsound = footstepsound3;
2058 whichsound = footstepsound4;
2062 if (animation[animTarget].label[frameTarget] == 1)
2063 whichsound = footstepsound3;
2065 whichsound = footstepsound4;
2067 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2068 if (animation[animTarget].attack != neutral) {
2069 unsigned r = abs(Random() % 3);
2071 whichsound = lowwhooshsound;
2073 whichsound = midwhooshsound;
2075 whichsound = highwhooshsound;
2077 if (animation[animTarget].attack == neutral)
2078 whichsound = movewhooshsound;
2079 } else if (animation[animTarget].label[frameTarget] == 4)
2080 whichsound = knifeswishsound;
2081 if (animation[animTarget].label[frameTarget] == 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 (animation[animTarget].label[frameTarget] == 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 ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2106 int whichsound = -1;
2107 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2108 if (animation[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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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[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[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[animTarget].label[frameCurrent] == 5) {
2334 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[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.num_joints; 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[animTarget].label[frameCurrent] == 5) {
2370 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[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.num_joints; 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[animTarget].label[frameCurrent] == 5) {
2403 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[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.num_joints; 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[animTarget].label[frameCurrent] == 5) {
2438 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[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.num_joints; 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[animTarget].label[frameCurrent] == 5) {
2473 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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[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[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[victim->animTarget].height == lowheight)
2844 relative = victim->coords - coords;
2846 Normalise(&relative);
2848 Normalise(&relative);
2849 for (int i = 0; i < victim->skeleton.num_joints; 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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 5) {
2916 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[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[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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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.num_joints; 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.num_joints; 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[animTarget].label[frameCurrent] == 5) {
3173 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3178 relative = victim->coords - coords;
3180 Normalise(&relative);
3184 if (animation[victim->animTarget].height == lowheight) {
3190 for (int i = 0; i < victim->skeleton.num_joints; 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.num_joints; 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[animTarget].label[frameCurrent] == 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[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3250 for (int i = 0; i < victim->skeleton.num_joints; 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.num_joints; 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.num_joints; 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.num_joints; 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[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3291 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 7) {
3392 Normalise(&relative);
3394 for (int i = 0; i < victim->skeleton.num_joints; 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[animTarget].label[frameCurrent] == 7) {
3442 Normalise(&relative);
3444 for (int i = 0; i < victim->skeleton.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 6) {
3570 victim->velocity = 0;
3571 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3572 victim->skeleton.joints[i].velocity = 0;
3574 if (animTarget == knifefollowanim) {
3576 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3577 victim->skeleton.joints[i].velocity = 0;
3580 if (weaponactive != -1 && animation[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[animTarget].label[frameCurrent] == 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[animTarget].label[frameCurrent] == 6) {
3628 victim->velocity = 0;
3629 for (int i = 0; i < victim->skeleton.num_joints; 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[animTarget].label[frameCurrent] == 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.num_joints; 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[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 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.num_joints; 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[animCurrent].numframes - 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[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[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[animCurrent].offset,0,yaw,0)*scale;
4043 targetoffset.y = coords.y;
4045 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4046 currentoffset = DoRotation(animation[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[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[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[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4144 if (!isRun() || !wasRun()) {
4145 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4146 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4147 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4148 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4150 if (isRun() && wasRun()) {
4152 tempspeed = velspeed;
4153 if (tempspeed < 10 * speedmult)
4154 tempspeed = 10 * speedmult;
4155 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4157 } else if (transspeed)
4158 target += multiplier * transspeed * speed * 2;
4160 if (!isRun() || !wasRun()) {
4161 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4162 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4163 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4164 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4168 if (animCurrent != animTarget)
4169 target = (target + oldtarget) / 2;
4172 frameCurrent = frameTarget;
4176 rot = targetrot * target;
4177 yaw += rot - oldrot;
4183 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4185 for (int i = 0; i < skeleton.num_joints; i++) {
4186 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4189 skeleton.FindForwards();
4191 for (int i = 0; i < skeleton.num_muscles; i++) {
4192 if (skeleton.muscles[i].visible) {
4193 skeleton.FindRotationMuscle(i, animTarget);
4196 for (int i = 0; i < skeleton.num_muscles; i++) {
4197 if (skeleton.muscles[i].visible) {
4198 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4199 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4200 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4201 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4202 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4203 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4208 for (int i = 0; i < skeleton.num_joints; i++) {
4209 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4212 skeleton.FindForwards();
4214 for (int i = 0; i < skeleton.num_muscles; i++) {
4215 if (skeleton.muscles[i].visible) {
4216 skeleton.FindRotationMuscle(i, animTarget);
4219 for (int i = 0; i < skeleton.num_muscles; i++) {
4220 if (skeleton.muscles[i].visible) {
4221 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4222 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4223 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4224 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4225 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4226 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4227 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4228 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4229 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4230 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4231 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4232 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4236 if (frameCurrent >= animation[animCurrent].numframes)
4237 frameCurrent = animation[animCurrent].numframes - 1;
4239 oldanimCurrent = animCurrent;
4240 oldanimTarget = animTarget;
4241 oldframeTarget = frameTarget;
4242 oldframeCurrent = frameCurrent;
4244 for (int i = 0; i < skeleton.num_joints; i++) {
4245 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4246 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4248 offset = currentoffset * (1 - target) + targetoffset * target;
4249 for (int i = 0; i < skeleton.num_muscles; i++) {
4250 if (skeleton.muscles[i].visible) {
4251 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4252 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4253 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4258 if (isLanding() && landhard) {
4261 animTarget = getLandhard();
4274 void Person::DoStuff()
4276 static XYZ terrainnormal;
4277 static XYZ flatfacing;
4278 static XYZ flatvelocity;
4279 static float flatvelspeed;
4283 static int bloodsize;
4284 static int startx, starty, endx, endy;
4285 static GLubyte color;
4286 static XYZ bloodvel;
4288 onfiredelay -= multiplier;
4289 if (onfiredelay < 0 && onfire) {
4290 if (Random() % 2 == 0) {
4296 crouchkeydowntime += multiplier;
4298 crouchkeydowntime = 0;
4299 jumpkeydowntime += multiplier;
4300 if (!jumpkeydown && skeleton.free)
4301 jumpkeydowntime = 0;
4303 if (hostile || damage > 0 || bloodloss > 0)
4306 if (isIdle() || isRun())
4309 if (num_weapons == 1 && weaponactive != -1)
4313 blooddimamount -= multiplier * .3;
4314 speechdelay -= multiplier;
4315 texupdatedelay -= multiplier;
4316 interestdelay -= multiplier;
4317 flamedelay -= multiplier;
4318 parriedrecently -= multiplier;
4320 victim = this->shared_from_this();
4325 speed = 1.1 * speedmult;
4327 speed = 1.0 * speedmult;
4329 rabbitkickragdoll = 0;
4333 if (id != 0 && (creature == rabbittype || difficulty != 2))
4335 if (id != 0 && creature == wolftype && difficulty == 2) {
4337 if (aitype != passivetype) {
4339 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) {
4345 if (animTarget == wolfrunninganim && !superruntoggle) {
4346 animTarget = getRun();
4350 if (weaponactive == -1 && num_weapons > 0) {
4351 if (weapons[weaponids[0]].getType() == staff) {
4357 burnt += multiplier;
4361 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4363 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4369 vel[0] = velocity.x;
4370 vel[1] = velocity.y;
4371 vel[2] = velocity.z;
4374 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4375 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4379 while (flamedelay < 0 && onfire) {
4381 howmany = abs(Random() % (skeleton.num_joints));
4382 if (skeleton.free) {
4383 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4384 flatfacing = skeleton.joints[howmany].position * scale + coords;
4386 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4387 flatvelocity = (coords - oldcoords) / multiplier / 2;
4389 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4392 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4394 howmany = abs(Random() % (skeleton.num_joints));
4395 if (skeleton.free) {
4396 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4397 flatfacing = skeleton.joints[howmany].position * scale + coords;
4399 flatvelocity = (coords - oldcoords) / multiplier / 2;
4400 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4402 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4406 bleeding -= multiplier * .3;
4407 if (bloodtoggle == 2) {
4408 skeleton.drawmodel.textureptr.bind();
4409 if ((bleeding <= 0) && (detail != 2))
4414 if (neckspurtamount > 0) {
4415 neckspurtamount -= multiplier;
4416 neckspurtdelay -= multiplier * 3;
4417 neckspurtparticledelay -= multiplier * 3;
4418 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4421 if (skeleton.free) {
4422 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4423 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4424 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4426 bloodvel.z = 5 * neckspurtamount;
4427 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4428 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4429 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4431 neckspurtparticledelay = .05;
4433 if (neckspurtdelay < 0) {
4438 if (deathbleeding > 0 && dead != 2) {
4439 if (deathbleeding < 5)
4440 bleeddelay -= deathbleeding * multiplier / 4;
4442 bleeddelay -= 5 * multiplier / 4;
4443 if (bleeddelay < 0 && bloodtoggle) {
4448 if (skeleton.free) {
4449 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4450 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4452 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4453 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4457 bloodloss += deathbleeding * multiplier * 80;
4458 deathbleeding -= multiplier * 1.6;
4459 if (deathbleeding < 0)
4461 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4462 if (weaponactive != -1) {
4463 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4464 weapons[weaponids[0]].velocity.x += .01;
4467 weaponids[0] = weaponids[num_weapons];
4468 if (weaponstuck == num_weapons)
4472 for (unsigned i = 0; i < Person::players.size(); i++) {
4473 Person::players[i]->wentforweapon = 0;
4481 if (!dead && creature == wolftype) {
4482 award_bonus(0, Wolfbonus);
4485 if (animTarget == knifefollowedanim && !skeleton.free) {
4486 for (int i = 0; i < skeleton.num_joints; i++) {
4487 skeleton.joints[i].velocity = 0;
4488 skeleton.joints[i].velocity.y = -2;
4491 if (id != 0 && unconscioustime > .1) {
4499 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4500 texupdatedelay = .12;
4502 bloodsize = 5 - realtexdetail;
4506 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4507 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4508 endx = startx + bloodsize;
4509 endy = starty + bloodsize;
4519 if (endx > skeleton.skinsize - 1) {
4520 endx = skeleton.skinsize - 1;
4523 if (endy > skeleton.skinsize - 1) {
4524 endy = skeleton.skinsize - 1;
4532 for (i = startx; i < endx; i++) {
4533 for (j = starty; j < endy; j++) {
4534 if (Random() % 2 == 0) {
4535 color = Random() % 85 + 170;
4536 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4537 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4538 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4539 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4544 skeleton.drawmodel.textureptr.bind();
4548 if (skeleton.free) {
4549 bleedx += 4 * direction / realtexdetail;
4551 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4553 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4555 bleedy -= 4 / realtexdetail;
4557 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4559 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4563 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4564 righthandmorphness = targetrighthandmorphness;
4565 righthandmorphstart = righthandmorphend;
4566 } else if (righthandmorphness > targetrighthandmorphness) {
4567 righthandmorphness -= multiplier * 4;
4568 } else if (righthandmorphness < targetrighthandmorphness) {
4569 righthandmorphness += multiplier * 4;
4572 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4573 lefthandmorphness = targetlefthandmorphness;
4574 lefthandmorphstart = lefthandmorphend;
4575 } else if (lefthandmorphness > targetlefthandmorphness) {
4576 lefthandmorphness -= multiplier * 4;
4577 } else if (lefthandmorphness < targetlefthandmorphness) {
4578 lefthandmorphness += multiplier * 4;
4581 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4582 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4583 tailmorphness = targettailmorphness;
4584 tailmorphstart = tailmorphend;
4585 } else if (tailmorphness > targettailmorphness) {
4586 tailmorphness -= multiplier * 10;
4587 } else if (tailmorphness < targettailmorphness) {
4588 tailmorphness += multiplier * 10;
4592 if (creature == wolftype) {
4593 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4594 tailmorphness = targettailmorphness;
4595 tailmorphstart = tailmorphend;
4596 } else if (tailmorphness > targettailmorphness) {
4597 tailmorphness -= multiplier * 2;
4598 } else if (tailmorphness < targettailmorphness) {
4599 tailmorphness += multiplier * 2;
4603 if (headmorphend == 3 || headmorphstart == 3) {
4604 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4605 headmorphness = targetheadmorphness;
4606 headmorphstart = headmorphend;
4607 } else if (headmorphness > targetheadmorphness) {
4608 headmorphness -= multiplier * 7;
4609 } else if (headmorphness < targetheadmorphness) {
4610 headmorphness += multiplier * 7;
4612 } else if (headmorphend == 5 || headmorphstart == 5) {
4613 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4614 headmorphness = targetheadmorphness;
4615 headmorphstart = headmorphend;
4616 } else if (headmorphness > targetheadmorphness) {
4617 headmorphness -= multiplier * 10;
4618 } else if (headmorphness < targetheadmorphness) {
4619 headmorphness += multiplier * 10;
4622 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4623 headmorphness = targetheadmorphness;
4624 headmorphstart = headmorphend;
4625 } else if (headmorphness > targetheadmorphness) {
4626 headmorphness -= multiplier * 4;
4627 } else if (headmorphness < targetheadmorphness) {
4628 headmorphness += multiplier * 4;
4632 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4633 chestmorphness = targetchestmorphness;
4634 chestmorphstart = chestmorphend;
4635 } else if (chestmorphness > targetchestmorphness) {
4636 chestmorphness -= multiplier;
4637 } else if (chestmorphness < targetchestmorphness) {
4638 chestmorphness += multiplier;
4641 if (dead != 2 && howactive <= typesleeping) {
4642 if (chestmorphstart == 0 && chestmorphend == 0) {
4644 targetchestmorphness = 1;
4647 if (chestmorphstart != 0 && chestmorphend != 0) {
4649 targetchestmorphness = 1;
4651 if (environment == snowyenvironment) {
4654 if (skeleton.free) {
4655 footvel = skeleton.specialforward[0] * -1;
4656 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4658 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4659 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4661 if (animTarget == sleepanim)
4662 footvel = DoRotation(footvel, 0, 90, 0);
4663 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4667 if (!dead && howactive < typesleeping) {
4668 blinkdelay -= multiplier * 2;
4669 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4671 targetheadmorphness = 1;
4673 blinkdelay = (float)(abs(Random() % 40)) / 5;
4675 if (headmorphstart == 3 && headmorphend == 3) {
4677 targetheadmorphness = 1;
4682 twitchdelay -= multiplier * 1.5;
4683 if (animTarget != hurtidleanim) {
4684 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4686 targetheadmorphness = 1;
4688 twitchdelay = (float)(abs(Random() % 40)) / 5;
4690 if (headmorphstart == 5 && headmorphend == 5) {
4692 targetheadmorphness = 1;
4696 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4697 twitchdelay3 -= multiplier * 1;
4698 if (Random() % 2 == 0) {
4699 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4700 righthandmorphness = 0;
4701 targetrighthandmorphness = 1;
4702 righthandmorphend = 1;
4703 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4705 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4706 righthandmorphness = 0;
4707 targetrighthandmorphness = 1;
4708 righthandmorphend = 0;
4711 if (Random() % 2 == 0) {
4712 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4713 lefthandmorphness = 0;
4714 targetlefthandmorphness = 1;
4715 lefthandmorphend = 1;
4716 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4718 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4719 lefthandmorphness = 0;
4720 targetlefthandmorphness = 1;
4721 lefthandmorphend = 0;
4727 if (creature == rabbittype) {
4728 if (howactive < typesleeping)
4729 twitchdelay2 -= multiplier * 1.5;
4731 twitchdelay2 -= multiplier * 0.5;
4732 if (howactive <= typesleeping) {
4733 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4735 targettailmorphness = 1;
4737 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4739 if (tailmorphstart == 1 && tailmorphend == 1) {
4741 targettailmorphness = 1;
4744 if (tailmorphstart == 2 && tailmorphend == 2) {
4746 targettailmorphness = 1;
4753 if (creature == wolftype) {
4754 twitchdelay2 -= multiplier * 1.5;
4755 if (tailmorphend != 0)
4756 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4758 targettailmorphness = 1;
4762 if (tailmorphend != 5)
4763 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4765 targettailmorphness = 1;
4769 if (twitchdelay2 <= 0) {
4770 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4772 targettailmorphness = 1;
4775 if (tailmorphstart == 1 && tailmorphend == 1) {
4777 targettailmorphness = 1;
4780 if (tailmorphstart == 2 && tailmorphend == 2) {
4782 targettailmorphness = 1;
4785 if (tailmorphstart == 3 && tailmorphend == 3) {
4787 targettailmorphness = 1;
4790 if (tailmorphstart == 4 && tailmorphend == 4) {
4792 targettailmorphness = 1;
4799 unconscioustime = 0;
4801 if (dead == 1 || howactive == typesleeping) {
4802 unconscioustime += multiplier;
4803 //If unconscious, close eyes and mouth
4804 if (righthandmorphend != 0)
4805 righthandmorphness = 0;
4806 righthandmorphend = 0;
4807 targetrighthandmorphness = 1;
4809 if (lefthandmorphend != 0)
4810 lefthandmorphness = 0;
4811 lefthandmorphend = 0;
4812 targetlefthandmorphness = 1;
4814 if (headmorphend != 3 && headmorphend != 5)
4817 targetheadmorphness = 1;
4821 if (howactive > typesleeping) {
4824 if (bloodtoggle && !bled) {
4825 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4827 if (bloodtoggle && !bled)
4828 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4829 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4830 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4834 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4839 if (dead == 2 || howactive > typesleeping) {
4840 //If dead, open mouth and hands
4841 if (righthandmorphend != 0)
4842 righthandmorphness = 0;
4843 righthandmorphend = 0;
4844 targetrighthandmorphness = 1;
4846 if (lefthandmorphend != 0)
4847 lefthandmorphness = 0;
4848 lefthandmorphend = 0;
4849 targetlefthandmorphness = 1;
4851 if (headmorphend != 2)
4854 targetheadmorphness = 1;
4857 if (stunned > 0 && !dead && headmorphend != 2) {
4858 if (headmorphend != 4)
4861 targetheadmorphness = 1;
4864 if (damage > damagetolerance && !dead) {
4867 unconscioustime = 0;
4869 if (creature == wolftype) {
4870 award_bonus(0, Wolfbonus);
4875 if (weaponactive != -1) {
4876 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4877 weapons[weaponids[0]].velocity.x += .01;
4880 weaponids[0] = weaponids[num_weapons];
4881 if (weaponstuck == num_weapons)
4885 for (unsigned i = 0; i < Person::players.size(); i++) {
4886 Person::players[i]->wentforweapon = 0;
4892 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4901 damage -= multiplier * 13;
4903 permanentdamage -= multiplier * 4;
4904 if (isIdle() || isCrouch()) {
4906 permanentdamage -= multiplier * 4;
4910 if (permanentdamage < 0)
4911 permanentdamage = 0;
4912 if (superpermanentdamage < 0)
4913 superpermanentdamage = 0;
4914 if (permanentdamage < superpermanentdamage) {
4915 permanentdamage = superpermanentdamage;
4917 if (damage < permanentdamage) {
4918 damage = permanentdamage;
4920 if (dead == 1 && damage < damagetolerance) {
4924 for (int i = 0; i < skeleton.num_joints; i++) {
4925 skeleton.joints[i].velocity = 0;
4928 if (permanentdamage > damagetolerance && dead != 2) {
4931 if (weaponactive != -1) {
4932 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4933 weapons[weaponids[0]].velocity.x += .01;
4936 weaponids[0] = weaponids[num_weapons];
4937 if (weaponstuck == num_weapons)
4941 for (unsigned i = 0; i < Person::players.size(); i++) {
4942 Person::players[i]->wentforweapon = 0;
4948 if (!dead && creature == wolftype) {
4949 award_bonus(0, Wolfbonus);
4952 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4953 award_bonus(id, touchofdeath);
4954 if (id != 0 && unconscioustime > .1) {
4962 emit_sound_at(breaksound, coords);
4965 if (skeleton.free == 1) {
4967 pause_sound(whooshsound);
4970 //If knocked over, open hands and close mouth
4971 if (righthandmorphend != 0)
4972 righthandmorphness = 0;
4973 righthandmorphend = 0;
4974 targetrighthandmorphness = 1;
4976 if (lefthandmorphend != 0)
4977 lefthandmorphness = 0;
4978 lefthandmorphend = 0;
4979 targetlefthandmorphness = 1;
4981 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4982 if (headmorphend != 0)
4985 targetheadmorphness = 1;
4989 skeleton.DoGravity(&scale);
4991 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4992 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4993 award_bonus(id, deepimpact);
4994 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4998 for (j = 0; j < skeleton.num_joints; j++) {
4999 average += skeleton.joints[j].position;
5003 coords += average * scale;
5004 for (j = 0; j < skeleton.num_joints; j++) {
5005 skeleton.joints[j].position -= average;
5007 average /= multiplier;
5010 for (int i = 0; i < skeleton.num_joints; i++) {
5011 velocity += skeleton.joints[i].velocity * scale;
5013 velocity /= skeleton.num_joints;
5015 if (!isnormal(velocity.x) && velocity.x) {
5019 if (findLength(&average) < 10 && dead && skeleton.free) {
5020 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5021 if (skeleton.longdead > 2000) {
5022 if (skeleton.longdead > 6000) {
5024 pause_sound(whooshsound);
5029 if (dead == 2 && bloodloss < damagetolerance) {
5031 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5033 if (bloodtoggle && !bled) {
5034 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5036 if (bloodtoggle && !bled)
5037 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5038 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5039 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5040 float size = .2 * 1.2;
5043 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5047 if (dead == 2 && bloodloss >= damagetolerance) {
5049 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5052 if (bloodtoggle && !bled) {
5053 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5055 if (bloodtoggle && !bled)
5056 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5057 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5058 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5062 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5069 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5070 bool canrecover = 1;
5071 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5072 startpoint = coords;
5075 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5077 if (velocity.y < -30)
5079 for (i = 0; i < objects.numobjects; i++) {
5080 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5081 colviewer = startpoint;
5082 coltarget = endpoint;
5083 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5092 terrainnormal = jointPos(groin) - jointPos(abdomen);
5093 if (joint(groin).locked && joint(abdomen).locked) {
5094 terrainnormal = jointPos(groin) - jointPos(abdomen);
5095 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5097 if (joint(abdomen).locked && joint(neck).locked) {
5098 terrainnormal = jointPos(abdomen) - jointPos(neck);
5099 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5101 if (joint(groin).locked && joint(neck).locked) {
5102 terrainnormal = jointPos(groin) - jointPos(neck);
5103 middle = (jointPos(groin) + jointPos(neck)) / 2;
5105 Normalise(&terrainnormal);
5107 targetyaw = -asin(0 - terrainnormal.x);
5108 targetyaw *= 360 / 6.28;
5109 if (terrainnormal.z < 0)
5110 targetyaw = 180 - targetyaw;
5114 animTarget = flipanim;
5115 crouchtogglekeydown = 1;
5120 animCurrent = tempanim;
5124 for (int i = 0; i < skeleton.num_joints; i++) {
5125 tempanimation.position[i][0] = skeleton.joints[i].position;
5126 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5131 if (findLength(&average) < 10 && !dead && skeleton.free) {
5132 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5133 if (skeleton.longdead > (damage + 500) * 1.5) {
5135 pause_sound(whooshsound);
5141 terrainnormal = jointPos(groin) - jointPos(abdomen);
5142 if (joint(groin).locked && joint(abdomen).locked) {
5143 terrainnormal = jointPos(groin) - jointPos(abdomen);
5144 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5146 if (joint(abdomen).locked && joint(neck).locked) {
5147 terrainnormal = jointPos(abdomen) - jointPos(neck);
5148 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5150 if (joint(groin).locked && joint(neck).locked) {
5151 terrainnormal = jointPos(groin) - jointPos(neck);
5152 middle = (jointPos(groin) + jointPos(neck)) / 2;
5154 Normalise(&terrainnormal);
5156 targetyaw = -asin(0 - terrainnormal.x);
5157 targetyaw *= 360 / 6.28;
5158 if (terrainnormal.z < 0)
5159 targetyaw = 180 - targetyaw;
5162 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5165 if (skeleton.forward.y < 0) {
5166 animTarget = getupfrombackanim;
5170 if (skeleton.forward.y > -.3) {
5171 animTarget = getupfromfrontanim;
5179 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5180 animTarget = rollanim;
5181 targetyaw = lookyaw;
5198 if ( !leftkeydown && !rightkeydown)
5205 if (abs(targettilt2) > 50)
5207 animCurrent = tempanim;
5210 tilt2 = targettilt2;
5212 if (middle.y > 0 && animTarget != rollanim)
5213 targetoffset.y = middle.y + 1;
5215 for (int i = 0; i < skeleton.num_joints; i++) {
5216 tempanimation.position[i][0] = skeleton.joints[i].position;
5217 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5224 if (num_weapons > 0)
5225 if (weapons[0].getType() == staff)
5227 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5228 if (velocity.y > -30) {
5230 tempvelocity = velocity;
5231 Normalise(&tempvelocity);
5232 targetyaw = -asin(0 - tempvelocity.x);
5233 targetyaw *= 360 / 6.28;
5235 targetyaw = 180 - targetyaw;
5239 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5240 animTarget = rollanim;
5243 animTarget = backhandspringanim;
5249 emit_sound_at(movewhooshsound, coords, 128.);
5251 animCurrent = animTarget;
5252 frameCurrent = frameTarget - 1;
5264 if (skeleton.freefall == 0)
5269 if (aitype != passivetype || skeleton.free == 1)
5270 if (findLengthfast(&velocity) > .1)
5271 for (i = 0; i < objects.numobjects; i++) {
5272 if (objects.type[i] == firetype)
5273 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) {
5275 if (!objects.onfire[i]) {
5276 emit_sound_at(firestartsound, objects.position[i]);
5278 objects.onfire[i] = 1;
5281 if (objects.onfire[i]) {
5286 if (objects.type[i] == bushtype)
5287 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) {
5289 if (!objects.onfire[i]) {
5290 emit_sound_at(firestartsound, objects.position[i]);
5292 objects.onfire[i] = 1;
5296 if (objects.onfire[i]) {
5300 if (objects.messedwith[i] <= 0) {
5304 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5307 addEnvSound(coords, 4 * findLength(&velocity));
5311 if (environment == grassyenvironment)
5312 howmany = findLength(&velocity) * 4;
5313 if (environment == snowyenvironment)
5314 howmany = findLength(&velocity) * 2;
5316 if (environment != desertenvironment)
5317 for (j = 0; j < howmany; j++) {
5318 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5319 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5320 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5323 pos.x += float(abs(Random() % 100) - 50) / 200;
5324 pos.y += float(abs(Random() % 100) - 50) / 200;
5325 pos.z += float(abs(Random() % 100) - 50) / 200;
5326 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);
5327 Sprite::setLastSpriteSpecial(1);
5329 howmany = findLength(&velocity) * 4;
5331 if (environment == snowyenvironment)
5332 for (j = 0; j < howmany; j++) {
5333 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5334 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5335 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5338 pos.x += float(abs(Random() % 100) - 50) / 200;
5339 pos.y += float(abs(Random() % 100) - 50) / 200;
5340 pos.z += float(abs(Random() % 100) - 50) / 200;
5341 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5342 Sprite::setLastSpriteSpecial(2);
5345 objects.rotx[i] += velocity.x * multiplier * 6;
5346 objects.roty[i] += velocity.z * multiplier * 6;
5347 objects.messedwith[i] = .5;
5350 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5351 if (objects.pitch[i] == 0)
5354 tempcoord = coords - objects.position[i];
5355 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5356 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5357 tempcoord += objects.position[i];
5359 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]) {
5360 if (objects.messedwith[i] <= 0) {
5364 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5367 addEnvSound(coords, 4 * findLength(&velocity));
5371 if (environment == grassyenvironment)
5372 howmany = findLength(&velocity) * 4;
5373 if (environment == snowyenvironment)
5374 howmany = findLength(&velocity) * 2;
5376 if (environment != desertenvironment)
5377 for (j = 0; j < howmany; j++) {
5378 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5379 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5380 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5382 pos += velocity * .1;
5384 pos.x += float(abs(Random() % 100) - 50) / 150;
5385 pos.y += float(abs(Random() % 100) - 50) / 150;
5386 pos.z += float(abs(Random() % 100) - 50) / 150;
5387 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);
5388 Sprite::setLastSpriteSpecial(1);
5390 howmany = findLength(&velocity) * 4;
5392 if (environment == snowyenvironment)
5393 for (j = 0; j < howmany; j++) {
5394 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5395 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5396 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5398 pos += velocity * .1;
5400 pos.x += float(abs(Random() % 100) - 50) / 150;
5401 pos.y += float(abs(Random() % 100) - 50) / 150;
5402 pos.z += float(abs(Random() % 100) - 50) / 150;
5403 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5404 Sprite::setLastSpriteSpecial(2);
5407 objects.messedwith[i] = .5;
5412 if (!skeleton.free) {
5415 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5418 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5420 if (tutoriallevel == 1 && id != 0)
5422 if (play && aitype != playercontrolled) {
5423 int whichsound = -1;
5424 i = abs(Random() % 4);
5425 if (speechdelay <= 0) {
5426 if (creature == rabbittype) {
5428 whichsound = rabbitchitter;
5430 whichsound = rabbitchitter2;
5432 if (creature == wolftype) {
5434 whichsound = growlsound;
5436 whichsound = growl2sound;
5441 if (whichsound != -1) {
5442 emit_sound_at(whichsound, coords);
5446 if (animTarget == staggerbackhighanim)
5448 if (animTarget == staggerbackhardanim)
5450 staggerdelay -= multiplier;
5451 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5453 if (velocity.y < -30 && animTarget == jumpdownanim)
5455 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5456 animTarget = getIdle();
5460 weaponmissdelay -= multiplier;
5461 highreversaldelay -= multiplier;
5462 lowreversaldelay -= multiplier;
5463 lastcollide -= multiplier;
5464 skiddelay -= multiplier;
5465 if (!isnormal(velocity.x) && velocity.x) {
5468 if (!isnormal(targettilt) && targettilt) {
5471 if (!isnormal(targettilt2) && targettilt2) {
5474 if (!isnormal(targetyaw) && targetyaw) {
5478 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5479 //open hands and close mouth
5480 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5481 righthandmorphness = 0;
5482 righthandmorphend = 0;
5483 targetrighthandmorphness = 1;
5486 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5487 lefthandmorphness = 0;
5488 lefthandmorphend = 0;
5489 targetlefthandmorphness = 1;
5492 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5495 targetheadmorphness = 1;
5499 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) {
5500 //open hands and mouth
5501 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5502 righthandmorphness = 0;
5503 righthandmorphend = 0;
5504 targetrighthandmorphness = 1;
5507 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5508 lefthandmorphness = 0;
5509 lefthandmorphend = 0;
5510 targetlefthandmorphness = 1;
5513 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5516 targetheadmorphness = 1;
5520 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5521 //close hands and mouth
5522 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5523 righthandmorphness = 0;
5524 righthandmorphend = 1;
5525 targetrighthandmorphness = 1;
5528 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5529 lefthandmorphness = 0;
5530 lefthandmorphend = 1;
5531 targetlefthandmorphness = 1;
5534 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5537 targetheadmorphness = 1;
5541 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) {
5542 //close hands and yell
5543 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5544 righthandmorphness = 0;
5545 righthandmorphend = 1;
5546 targetrighthandmorphness = 1;
5549 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5550 lefthandmorphness = 0;
5551 lefthandmorphend = 1;
5552 targetlefthandmorphness = 1;
5555 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5558 targetheadmorphness = 1;
5565 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5566 (victim->aitype != searchtype) && (aitype != passivetype) &&
5567 (aitype != searchtype) && (victim->id < Person::players.size())) {
5568 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5572 if (!dead && animTarget != hurtidleanim)
5573 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5574 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5577 targetheadmorphness = 1;
5581 if (weaponactive != -1) {
5582 if (weapons[weaponids[weaponactive]].getType() != staff) {
5583 righthandmorphstart = 1;
5584 righthandmorphend = 1;
5586 if (weapons[weaponids[weaponactive]].getType() == staff) {
5587 righthandmorphstart = 2;
5588 righthandmorphend = 2;
5590 targetrighthandmorphness = 1;
5593 terrainnormal = terrain.getNormal(coords.x, coords.z);
5595 if (animation[animTarget].attack != reversal) {
5596 if (!isnormal(coords.x))
5604 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5605 facing = flatfacing;
5606 ReflectVector(&facing, terrainnormal);
5609 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5611 targettilt2 = -facing.y * 20;
5616 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5618 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5619 flatvelocity = velocity;
5621 flatvelspeed = findLength(&flatvelocity);
5622 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5623 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5628 if (targettilt > 25)
5630 if (targettilt < -25)
5634 if (targettilt2 > 45)
5636 if (targettilt2 < -45)
5638 if (abs(tilt2 - targettilt2) < multiplier * 400)
5639 tilt2 = targettilt2;
5640 else if (tilt2 > targettilt2) {
5641 tilt2 -= multiplier * 400;
5642 } else if (tilt2 < targettilt2) {
5643 tilt2 += multiplier * 400;
5645 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5652 if (!isnormal(targettilt) && targettilt) {
5655 if (!isnormal(targettilt2) && targettilt2) {
5660 if (animTarget == rabbittackleanim) {
5661 velocity += facing * multiplier * speed * 700 * scale;
5662 velspeed = findLength(&velocity);
5663 if (velspeed > speed * 65 * scale) {
5664 velocity /= velspeed;
5665 velspeed = speed * 65 * scale;
5666 velocity *= velspeed;
5668 velocity.y += gravity * multiplier * 20;
5669 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5670 velspeed = findLength(&velocity);
5671 velocity = flatfacing * velspeed;
5673 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5674 if (isRun() || animTarget == rabbitkickanim) {
5675 velocity += facing * multiplier * speed * 700 * scale;
5676 velspeed = findLength(&velocity);
5677 if (velspeed > speed * 45 * scale) {
5678 velocity /= velspeed;
5679 velspeed = speed * 45 * scale;
5680 velocity *= velspeed;
5682 velocity.y += gravity * multiplier * 20;
5683 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5684 velspeed = findLength(&velocity);
5685 if (velspeed < speed * 30 * scale)
5686 velspeed = speed * 30 * scale;
5687 velocity = flatfacing * velspeed;
5689 } else if (isRun()) {
5690 velocity += facing * multiplier * speed * 700 * scale;
5691 velspeed = findLength(&velocity);
5692 if (creature == rabbittype) {
5693 if (velspeed > speed * 55 * scale) {
5694 velocity /= velspeed;
5695 velspeed = speed * 55 * scale;
5696 velocity *= velspeed;
5699 if (creature == wolftype) {
5700 if (velspeed > speed * 75 * scale) {
5701 velocity /= velspeed;
5702 velspeed = speed * 75 * scale;
5703 velocity *= velspeed;
5706 velocity.y += gravity * multiplier * 20;
5707 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5708 velspeed = findLength(&velocity);
5709 velocity = flatfacing * velspeed;
5712 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5713 velocity += facing * multiplier * speed * 700 * scale;
5714 velspeed = findLength(&velocity);
5715 if (velspeed > speed * 45 * scale) {
5716 velocity /= velspeed;
5717 velspeed = speed * 45 * scale;
5718 velocity *= velspeed;
5720 velocity.y += gravity * multiplier * 20;
5721 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5722 velspeed = findLength(&velocity);
5723 velocity = flatfacing * velspeed;
5726 if (animTarget == sneakanim || animTarget == walkanim) {
5727 velocity += facing * multiplier * speed * 700 * scale;
5728 velspeed = findLength(&velocity);
5729 if (velspeed > speed * 12 * scale) {
5730 velocity /= velspeed;
5731 velspeed = speed * 12 * scale;
5732 velocity *= velspeed;
5734 velocity.y += gravity * multiplier * 20;
5735 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5736 velspeed = findLength(&velocity);
5737 velocity = flatfacing * velspeed;
5740 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5741 velocity += facing * multiplier * speed * 700 * scale;
5742 velspeed = findLength(&velocity);
5743 if (velspeed > speed * 2 * scale) {
5744 velocity /= velspeed;
5745 velspeed = speed * 2 * scale;
5746 velocity *= velspeed;
5748 velocity.y += gravity * multiplier * 20;
5749 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5750 velspeed = findLength(&velocity);
5751 velocity = flatfacing * velspeed;
5755 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5756 velocity -= facing * multiplier * speed * 700 * scale;
5757 velspeed = findLength(&velocity);
5758 if (velspeed > speed * 2 * scale) {
5759 velocity /= velspeed;
5760 velspeed = speed * 2 * scale;
5761 velocity *= velspeed;
5763 velocity.y += gravity * multiplier * 20;
5764 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5765 velspeed = findLength(&velocity);
5766 velocity = flatfacing * velspeed * -1;
5769 if (animTarget == fightsidestep) {
5770 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5771 velspeed = findLength(&velocity);
5772 if (velspeed > speed * 12 * scale) {
5773 velocity /= velspeed;
5774 velspeed = speed * 12 * scale;
5775 velocity *= velspeed;
5777 velocity.y += gravity * multiplier * 20;
5778 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5779 velspeed = findLength(&velocity);
5780 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5783 if (animTarget == staggerbackhighanim) {
5784 coords -= facing * multiplier * speed * 16 * scale;
5787 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5788 coords -= facing * multiplier * speed * 20 * scale;
5792 if (animTarget == backhandspringanim) {
5793 //coords-=facing*multiplier*50*scale;
5794 velocity += facing * multiplier * speed * 700 * scale * -1;
5795 velspeed = findLength(&velocity);
5796 if (velspeed > speed * 50 * scale) {
5797 velocity /= velspeed;
5798 velspeed = speed * 50 * scale;
5799 velocity *= velspeed;
5801 velocity.y += gravity * multiplier * 20;
5802 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5803 velspeed = findLength(&velocity);
5804 velocity = flatfacing * velspeed * -1;
5806 if (animTarget == dodgebackanim) {
5807 //coords-=facing*multiplier*50*scale;
5808 velocity += facing * multiplier * speed * 700 * scale * -1;
5809 velspeed = findLength(&velocity);
5810 if (velspeed > speed * 60 * scale) {
5811 velocity /= velspeed;
5812 velspeed = speed * 60 * scale;
5813 velocity *= velspeed;
5815 velocity.y += gravity * multiplier * 20;
5816 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5817 velspeed = findLength(&velocity);
5818 velocity = flatfacing * velspeed * -1;
5821 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5822 velspeed = findLength(&velocity);
5826 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5827 velocity.y += gravity * multiplier;
5830 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5831 coords += velocity * multiplier;
5833 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5834 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5837 if (animTarget == jumpupanim) {
5839 animTarget = getIdle();
5846 pause_sound(whooshsound);
5847 OPENAL_SetVolume(channels[whooshsound], 0);
5850 if (animTarget == jumpdownanim || isFlip()) {
5851 if (isFlip())jumppower = -4;
5852 animTarget = getLanding();
5853 emit_sound_at(landsound, coords, 128.);
5856 addEnvSound(coords);
5861 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5862 coords.y += gravity * multiplier * 2;
5863 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5864 coords.y = terrain.getHeight(coords.x, coords.z);
5869 if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || animation[animTarget].attack || (animTarget == rollanim && animation[animTarget].label[frameTarget] == 6)) {
5870 velspeed = findLength(&velocity);
5872 if (velspeed < multiplier * 300 * scale) {
5875 velocity -= velocity / velspeed * multiplier * 300 * scale;
5876 if (velspeed > 5 && (isLanding() || isLandhard())) {
5877 skiddingdelay += multiplier;
5878 if (skiddelay <= 0) {
5879 FootLand(leftfoot, .5);
5880 FootLand(rightfoot, .5);
5888 velspeed = findLength(&velocity);
5890 if (velspeed < multiplier * 600 * scale) {
5893 velocity -= velocity / velspeed * multiplier * 600 * scale;
5895 if (velspeed > 5 && (isLanding() || isLandhard())) {
5896 skiddingdelay += multiplier;
5897 if (skiddelay <= 0) {
5898 FootLand(leftfoot, .5);
5899 FootLand(rightfoot, .5);
5906 if (skiddingdelay < 0)
5907 skiddingdelay += multiplier;
5908 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5910 if (!onterrain || environment == grassyenvironment) {
5911 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5913 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5917 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5918 terrainnormal = victim->coords - coords;
5919 Normalise(&terrainnormal);
5920 targetyaw = -asin(0 - terrainnormal.x);
5921 targetyaw *= 360 / 6.28;
5922 if (terrainnormal.z < 0)
5923 targetyaw = 180 - targetyaw;
5924 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5927 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5928 targetyaw = victim->targetyaw;
5930 if (animTarget == rabbittacklinganim) {
5931 coords = victim->coords;
5934 skeleton.oldfree = skeleton.free;
5938 midterrain.x = terrain.size * terrain.scale / 2;
5939 midterrain.z = terrain.size * terrain.scale / 2;
5940 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5942 tempposit = coords - midterrain;
5944 Normalise(&tempposit);
5945 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5946 coords.x = tempposit.x + midterrain.x;
5947 coords.z = tempposit.z + midterrain.z;
5953 * inverse kinematics helper function
5955 void IKHelper(Person *p, float interp)
5957 XYZ point, change, change2;
5958 float heightleft, heightright;
5960 // TODO: implement localToWorld and worldToLocal
5961 // but keep in mind it won't be the same math if player is ragdolled or something
5962 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5963 // then comb through code for places where to use it
5965 // point = localToWorld(jointPos(leftfoot))
5966 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5967 // adjust height of foot
5968 heightleft = terrain.getHeight(point.x, point.z) + .04;
5969 point.y = heightleft;
5970 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5971 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5972 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5973 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5974 // move ankle along with foot
5975 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5976 // average knee pos between old and new pos
5977 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5979 // do same as above for right leg
5980 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5981 heightright = terrain.getHeight(point.x, point.z) + .04;
5982 point.y = heightright;
5983 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5984 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5985 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5986 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5987 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5989 // fix up skeleton now that we've moved body parts?
5990 p->skeleton.DoConstraints(&p->coords, &p->scale);
5997 int Person::DrawSkeleton()
5999 int oldplayerdetail;
6000 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6001 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6011 glAlphaFunc(GL_GREATER, 0.0001);
6013 float terrainheight;
6017 if (!isnormal(tilt))
6019 if (!isnormal(tilt2))
6021 oldplayerdetail = playerdetail;
6023 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6026 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6029 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6034 if (playerdetail != oldplayerdetail) {
6036 normalsupdatedelay = 0;
6038 static float updatedelaychange;
6039 static float morphness;
6040 static float framemult;
6042 skeleton.FindForwards();
6043 if (howactive == typesittingwall) {
6044 skeleton.specialforward[1] = 0;
6045 skeleton.specialforward[1].z = 1;
6051 static int weaponattachmuscle;
6052 static int weaponrotatemuscle;
6053 static XYZ weaponpoint;
6054 static int start, endthing;
6055 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6056 if (!isSleeping() && !isSitting()) {
6057 // TODO: give these meaningful names
6058 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6059 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6060 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6061 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6063 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6065 if (creature == wolftype)
6069 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6070 IKHelper(this, target);
6071 if (creature == wolftype)
6072 IKHelper(this, target);
6075 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6076 IKHelper(this, 1 - target);
6077 if (creature == wolftype)
6078 IKHelper(this, 1 - target);
6082 if (!skeleton.free && (!animation[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || animation[animTarget].label[frameTarget] == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
6085 targetheadyaw = -targetyaw;
6086 targetheadpitch = 0;
6087 if (animation[animTarget].attack == 3)
6088 targetheadyaw += 180;
6090 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6091 skeleton.drawmodel.vertex[i] = 0;
6092 skeleton.drawmodel.vertex[i].y = 999;
6094 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6095 skeleton.drawmodellow.vertex[i] = 0;
6096 skeleton.drawmodellow.vertex[i].y = 999;
6098 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6099 skeleton.drawmodelclothes.vertex[i] = 0;
6100 skeleton.drawmodelclothes.vertex[i].y = 999;
6102 for (int i = 0; i < skeleton.num_muscles; i++) {
6103 // convenience renames
6104 const int p1 = skeleton.muscles[i].parent1->label;
6105 const int p2 = skeleton.muscles[i].parent2->label;
6107 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6112 if (p1 == righthand || p2 == righthand) {
6113 morphness = righthandmorphness;
6114 start = righthandmorphstart;
6115 endthing = righthandmorphend;
6117 if (p1 == lefthand || p2 == lefthand) {
6118 morphness = lefthandmorphness;
6119 start = lefthandmorphstart;
6120 endthing = lefthandmorphend;
6122 if (p1 == head || p2 == head) {
6123 morphness = headmorphness;
6124 start = headmorphstart;
6125 endthing = headmorphend;
6127 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6128 morphness = chestmorphness;
6129 start = chestmorphstart;
6130 endthing = chestmorphend;
6132 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6133 morphness = tailmorphness;
6134 start = tailmorphstart;
6135 endthing = tailmorphend;
6138 skeleton.FindRotationMuscle(i, animTarget);
6139 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6140 glMatrixMode(GL_MODELVIEW);
6144 glRotatef(tilt2, 1, 0, 0);
6146 glRotatef(tilt, 0, 0, 1);
6149 glTranslatef(mid.x, mid.y, mid.z);
6151 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6152 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6154 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6155 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6157 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6158 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6160 if (playerdetail || skeleton.free == 3) {
6161 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6162 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6163 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6164 glMatrixMode(GL_MODELVIEW);
6166 if (p1 == abdomen || p2 == abdomen)
6167 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6168 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6169 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6170 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6171 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6172 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6173 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6174 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6175 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6176 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6177 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6178 if (p1 == head || p2 == head)
6179 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6180 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6181 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6182 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6183 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6184 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6185 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6189 if (!playerdetail || skeleton.free == 3) {
6190 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6191 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6192 glMatrixMode(GL_MODELVIEW);
6194 if (p1 == abdomen || p2 == abdomen)
6195 glTranslatef(v0.x * proportionbody.x,
6196 v0.y * proportionbody.y,
6197 v0.z * proportionbody.z);
6198 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6199 glTranslatef(v0.x * proportionarms.x,
6200 v0.y * proportionarms.y,
6201 v0.z * proportionarms.z);
6202 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6203 glTranslatef(v0.x * proportionlegs.x,
6204 v0.y * proportionlegs.y,
6205 v0.z * proportionlegs.z);
6206 if (p1 == head || p2 == head)
6207 glTranslatef(v0.x * proportionhead.x,
6208 v0.y * proportionhead.y,
6209 v0.z * proportionhead.z);
6211 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6212 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6213 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6214 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6220 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6221 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6223 glMatrixMode(GL_MODELVIEW);
6227 glRotatef(tilt2, 1, 0, 0);
6229 glRotatef(tilt, 0, 0, 1);
6230 glTranslatef(mid.x, mid.y, mid.z);
6231 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6232 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6234 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6235 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6237 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6238 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6240 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6241 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6242 glMatrixMode(GL_MODELVIEW);
6244 if (p1 == abdomen || p2 == abdomen)
6245 glTranslatef(v0.x * proportionbody.x,
6246 v0.y * proportionbody.y,
6247 v0.z * proportionbody.z);
6248 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6249 glTranslatef(v0.x * proportionarms.x,
6250 v0.y * proportionarms.y,
6251 v0.z * proportionarms.z);
6252 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6253 glTranslatef(v0.x * proportionlegs.x,
6254 v0.y * proportionlegs.y,
6255 v0.z * proportionlegs.z);
6256 if (p1 == head || p2 == head)
6257 glTranslatef(v0.x * proportionhead.x,
6258 v0.y * proportionhead.y,
6259 v0.z * proportionhead.z);
6260 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6261 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6262 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6263 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6268 updatedelay = 1 + (float)(Random() % 100) / 1000;
6270 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6271 normalsupdatedelay = 1;
6272 if (playerdetail || skeleton.free == 3)
6273 skeleton.drawmodel.CalculateNormals(0);
6274 if (!playerdetail || skeleton.free == 3)
6275 skeleton.drawmodellow.CalculateNormals(0);
6276 if (skeleton.clothes)
6277 skeleton.drawmodelclothes.CalculateNormals(0);
6279 if (playerdetail || skeleton.free == 3)
6280 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6281 if (!playerdetail || skeleton.free == 3)
6282 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6283 if (skeleton.clothes) {
6284 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6289 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6290 if (updatedelaychange > -realmultiplier * 30)
6291 updatedelaychange = -realmultiplier * 30;
6292 if (updatedelaychange > -framemult * 4)
6293 updatedelaychange = -framemult * 4;
6294 if (skeleton.free == 1)
6295 updatedelaychange *= 6;
6297 updatedelaychange *= 8;
6298 updatedelay += updatedelaychange;
6300 glMatrixMode(GL_MODELVIEW);
6302 glTranslatef(coords.x, coords.y - .02, coords.z);
6303 if (!skeleton.free) {
6304 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6305 glRotatef(yaw, 0, 1, 0);
6309 glColor4f(.4, 1, .4, 1);
6310 glDisable(GL_LIGHTING);
6311 glDisable(GL_TEXTURE_2D);
6314 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6315 XYZ &v0 = skeleton.drawmodel.vertex[i];
6316 glVertex3f(v0.x, v0.y, v0.z);
6322 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6323 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6324 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6325 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6326 glVertex3f(v0.x, v0.y, v0.z);
6327 glVertex3f(v1.x, v1.y, v1.z);
6328 glVertex3f(v1.x, v1.y, v1.z);
6329 glVertex3f(v2.x, v2.y, v2.z);
6330 glVertex3f(v2.x, v2.y, v2.z);
6331 glVertex3f(v0.x, v0.y, v0.z);
6337 terrainlight = terrain.getLighting(coords.x, coords.z);
6338 distance = distsq(&viewer, &coords);
6339 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6343 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6344 if (terrainheight < 1)
6346 if (terrainheight > 1.7)
6347 terrainheight = 1.7;
6349 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6350 glDisable(GL_BLEND);
6351 glAlphaFunc(GL_GREATER, 0.0001);
6352 glEnable(GL_TEXTURE_2D);
6354 glDisable(GL_TEXTURE_2D);
6355 glColor4f(.7, .35, 0, .5);
6357 glEnable(GL_LIGHTING);
6360 if (tutoriallevel && id != 0) {
6361 glColor4f(.7, .7, .7, 0.6);
6363 glEnable(GL_LIGHTING);
6365 if (canattack && cananger)
6366 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6367 glDisable(GL_TEXTURE_2D);
6368 glColor4f(1, 0, 0, 0.8);
6370 glMatrixMode(GL_TEXTURE);
6372 glTranslatef(0, -smoketex, 0);
6373 glTranslatef(-smoketex, 0, 0);
6377 if ((tutoriallevel && id != 0))
6378 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6380 skeleton.drawmodel.draw();
6383 if (!playerdetail) {
6384 if ((tutoriallevel && id != 0))
6385 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6387 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6390 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6391 if (tutoriallevel && id != 0) {
6393 glMatrixMode(GL_MODELVIEW);
6394 glEnable(GL_TEXTURE_2D);
6395 glColor4f(.7, .7, .7, 0.6);
6397 glEnable(GL_LIGHTING);
6399 if (canattack && cananger)
6400 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6401 glDisable(GL_TEXTURE_2D);
6402 glColor4f(1, 0, 0, 0.8);
6404 glMatrixMode(GL_TEXTURE);
6406 glTranslatef(0, -smoketex * .6, 0);
6407 glTranslatef(smoketex * .6, 0, 0);
6410 if ((tutoriallevel && id != 0))
6411 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6413 skeleton.drawmodel.draw();
6416 if (!playerdetail) {
6417 if ((tutoriallevel && id != 0))
6418 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6420 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6425 if (tutoriallevel && id != 0) {
6427 glMatrixMode(GL_MODELVIEW);
6428 glEnable(GL_TEXTURE_2D);
6430 if (skeleton.clothes) {
6434 skeleton.drawmodelclothes.draw();
6436 skeleton.drawmodelclothes.drawimmediate();
6442 if (num_weapons > 0) {
6443 for (k = 0; k < num_weapons; k++) {
6445 if (weaponactive == k) {
6446 if (weapons[i].getType() != staff) {
6447 for (j = 0; j < skeleton.num_muscles; j++) {
6448 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6449 weaponattachmuscle = j;
6452 for (j = 0; j < skeleton.num_muscles; j++) {
6453 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].numvertices > 0) {
6454 weaponrotatemuscle = j;
6457 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6458 if (creature == wolftype)
6459 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6461 if (weapons[i].getType() == staff) {
6462 for (j = 0; j < skeleton.num_muscles; j++) {
6463 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6464 weaponattachmuscle = j;
6467 for (j = 0; j < skeleton.num_muscles; j++) {
6468 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].numvertices > 0) {
6469 weaponrotatemuscle = j;
6472 //weaponpoint=jointPos(rightwrist);
6473 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6474 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6475 XYZ tempnormthing, vec1, vec2;
6476 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6477 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6478 CrossProduct(&vec1, &vec2, &tempnormthing);
6479 Normalise(&tempnormthing);
6480 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6481 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6484 if (weaponactive != k && weaponstuck != k) {
6485 if (weapons[i].getType() == knife)
6486 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6487 if (weapons[i].getType() == sword)
6488 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6489 if (weapons[i].getType() == staff)
6490 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6491 for (j = 0; j < skeleton.num_muscles; j++) {
6492 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].numvertices > 0) {
6493 weaponrotatemuscle = j;
6497 if (weaponstuck == k) {
6498 if (weaponstuckwhere == 0)
6499 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6501 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6502 for (j = 0; j < skeleton.num_muscles; j++) {
6503 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].numvertices > 0) {
6504 weaponrotatemuscle = j;
6508 if (skeleton.free) {
6509 weapons[i].position = weaponpoint * scale + coords;
6510 weapons[i].bigrotation = 0;
6511 weapons[i].bigtilt = 0;
6512 weapons[i].bigtilt2 = 0;
6514 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;
6515 weapons[i].bigrotation = yaw;
6516 weapons[i].bigtilt = tilt;
6517 weapons[i].bigtilt2 = tilt2;
6519 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6520 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6521 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6522 if (weaponactive == k) {
6523 if (weapons[i].getType() == knife) {
6524 weapons[i].smallrotation = 180;
6525 weapons[i].smallrotation2 = 0;
6526 if (isCrouch() || wasCrouch()) {
6527 weapons[i].smallrotation2 = 20;
6529 if (animTarget == hurtidleanim) {
6530 weapons[i].smallrotation2 = 50;
6532 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6533 XYZ temppoint1, temppoint2;
6536 temppoint1 = jointPos(righthand);
6537 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6538 distance = findDistance(&temppoint1, &temppoint2);
6539 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6540 weapons[i].rotation2 *= 360 / 6.28;
6543 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6544 weapons[i].rotation1 *= 360 / 6.28;
6545 weapons[i].rotation3 = 0;
6546 weapons[i].smallrotation = -90;
6547 weapons[i].smallrotation2 = 0;
6548 if (temppoint1.x > temppoint2.x)
6549 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6551 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6552 XYZ temppoint1, temppoint2;
6555 temppoint1 = jointPos(righthand);
6556 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6557 distance = findDistance(&temppoint1, &temppoint2);
6558 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6559 weapons[i].rotation2 *= 360 / 6.28;
6562 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6563 weapons[i].rotation1 *= 360 / 6.28;
6564 weapons[i].rotation3 = 0;
6565 weapons[i].smallrotation = 90;
6566 weapons[i].smallrotation2 = 0;
6567 if (temppoint1.x > temppoint2.x)
6568 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6570 if (animTarget == knifethrowanim) {
6571 weapons[i].smallrotation = 90;
6572 //weapons[i].smallrotation2=-90;
6573 weapons[i].smallrotation2 = 0;
6574 weapons[i].rotation1 = 0;
6575 weapons[i].rotation2 = 0;
6576 weapons[i].rotation3 = 0;
6578 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6579 weapons[i].smallrotation = -90;
6580 weapons[i].rotation1 = 0;
6581 weapons[i].rotation2 = 0;
6582 weapons[i].rotation3 = 0;
6585 if (weapons[i].getType() == sword) {
6586 weapons[i].smallrotation = 0;
6587 weapons[i].smallrotation2 = 0;
6588 if (animTarget == knifethrowanim) {
6589 weapons[i].smallrotation = -90;
6590 weapons[i].smallrotation2 = 0;
6591 weapons[i].rotation1 = 0;
6592 weapons[i].rotation2 = 0;
6593 weapons[i].rotation3 = 0;
6595 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)) {
6596 XYZ temppoint1, temppoint2;
6599 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6600 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6601 distance = findDistance(&temppoint1, &temppoint2);
6602 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6603 weapons[i].rotation2 *= 360 / 6.28;
6606 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6607 weapons[i].rotation1 *= 360 / 6.28;
6608 weapons[i].rotation3 = 0;
6609 weapons[i].smallrotation = 90;
6610 weapons[i].smallrotation2 = 0;
6611 if (temppoint1.x > temppoint2.x)
6612 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6615 if (weapons[i].getType() == staff) {
6616 weapons[i].smallrotation = 100;
6617 weapons[i].smallrotation2 = 0;
6618 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6619 XYZ temppoint1, temppoint2;
6622 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6623 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6624 distance = findDistance(&temppoint1, &temppoint2);
6625 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6626 weapons[i].rotation2 *= 360 / 6.28;
6629 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6630 weapons[i].rotation1 *= 360 / 6.28;
6631 weapons[i].rotation3 = 0;
6632 weapons[i].smallrotation = 90;
6633 weapons[i].smallrotation2 = 0;
6634 if (temppoint1.x > temppoint2.x)
6635 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6639 if (weaponactive != k && weaponstuck != k) {
6640 if (weapons[i].getType() == knife) {
6641 weapons[i].smallrotation = -70;
6642 weapons[i].smallrotation2 = 10;
6644 if (weapons[i].getType() == sword) {
6645 weapons[i].smallrotation = -100;
6646 weapons[i].smallrotation2 = -8;
6648 if (weapons[i].getType() == staff) {
6649 weapons[i].smallrotation = -100;
6650 weapons[i].smallrotation2 = -8;
6653 if (weaponstuck == k) {
6654 if (weaponstuckwhere == 0)
6655 weapons[i].smallrotation = 180;
6657 weapons[i].smallrotation = 0;
6658 weapons[i].smallrotation2 = 10;
6667 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6669 if (animCurrent != animTarget)
6671 if (skeleton.free == 2)
6680 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6683 static float distance;
6684 static float olddistance;
6685 static int intersecting;
6686 static int firstintersecting;
6689 static XYZ start, end;
6690 static float slopethreshold = -.4;
6692 firstintersecting = -1;
6696 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6699 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6700 for (i = 0; i < 4; i++) {
6701 for (j = 0; j < model->TriangleNum; j++) {
6702 if (model->facenormals[j].y <= slopethreshold) {
6704 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)));
6705 if (distance < radius) {
6706 point = *p1 - model->facenormals[j] * distance;
6707 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]]))
6710 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6711 &model->vertex[model->Triangles[j].vertex[1]],
6714 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6715 &model->vertex[model->Triangles[j].vertex[2]],
6718 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6719 &model->vertex[model->Triangles[j].vertex[2]],
6722 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6726 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)) {
6727 p1->y = point.y + radius;
6728 if ((animTarget == jumpdownanim || isFlip())) {
6729 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6732 if (animTarget == jumpupanim) {
6734 animTarget = getIdle();
6741 pause_sound(whooshsound);
6742 OPENAL_SetVolume(channels[whooshsound], 0);
6745 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6748 animTarget = getLanding();
6749 emit_sound_at(landsound, coords, 128.);
6752 addEnvSound(coords);
6759 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6760 olddistance = distance;
6761 firstintersecting = j;
6766 for (j = 0; j < model->TriangleNum; j++) {
6767 if (model->facenormals[j].y > slopethreshold) {
6770 start.y -= radius / 4;
6771 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6772 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6773 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6774 distance = abs((model->facenormals[j].x * start.x)
6775 + (model->facenormals[j].y * start.y)
6776 + (model->facenormals[j].z * start.z)
6777 - ((model->facenormals[j].x * v0.x)
6778 + (model->facenormals[j].y * v0.y)
6779 + (model->facenormals[j].z * v0.z)));
6780 if (distance < radius * .5) {
6781 point = start - model->facenormals[j] * distance;
6782 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6785 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6787 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6789 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6791 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6792 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6794 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6795 if (findLengthfast(&start) < findLengthfast(&velocity))
6798 *p1 += model->facenormals[j] * (distance - radius * .5);
6801 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6802 olddistance = distance;
6803 firstintersecting = j;
6810 *p = DoRotation(*p, 0, *rotate, 0);
6813 *p1 = DoRotation(*p1, 0, *rotate, 0);
6815 return firstintersecting;
6818 void Person::takeWeapon(int weaponId)
6821 weapons[weaponId].owner = id;
6822 if (num_weapons > 0) {
6823 weaponids[num_weapons] = weaponids[0];
6826 weaponids[0] = weaponId;
6829 void Person::addClothes()
6831 if (numclothes > 0) {
6832 for (int i = 0; i < numclothes; i++) {
6839 bool Person::addClothes(const int& clothesId)
6842 const std::string fileName = clothes[clothesId];
6844 GLubyte* array = &skeleton.skinText[0];
6848 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6853 float tintr = clothestintr[clothesId];
6854 float tintg = clothestintg[clothesId];
6855 float tintb = clothestintb[clothesId];
6857 if (tintr > 1) tintr = 1;
6858 if (tintg > 1) tintg = 1;
6859 if (tintb > 1) tintb = 1;
6861 if (tintr < 0) tintr = 0;
6862 if (tintg < 0) tintg = 0;
6863 if (tintb < 0) tintb = 0;
6865 int bytesPerPixel = texture.bpp / 8;
6869 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6870 if (bytesPerPixel == 3)
6872 else if ((i + 1) % 4 == 0)
6873 alphanum = texture.data[i];
6874 if ((i + 1) % 4 || bytesPerPixel == 3) {
6876 texture.data[i] *= tintr;
6878 texture.data[i] *= tintg;
6880 texture.data[i] *= tintb;
6881 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);