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 <**/
22 #include "Animation/Animation.h"
23 #include "Audio/openal_wrapper.h"
24 #include "Audio/Sounds.h"
25 #include "Level/Awards.h"
26 #include "Level/Dialog.h"
27 #include "Objects/Person.h"
28 #include "Utils/Folders.h"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern Objects objects;
49 extern bool autoslomo;
50 extern float camerashake;
52 extern float viewdistance;
53 extern float blackout;
54 extern int difficulty;
56 extern float fadestart;
58 extern bool winfreeze;
59 extern bool showpoints;
60 extern bool immediate;
61 extern int tutoriallevel;
62 extern float smoketex;
63 extern int tutorialstage;
64 extern bool reversaltrain;
65 extern bool canattack;
67 extern float damagedealt;
69 extern float hostiletime;
71 extern bool gamestarted;
73 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
78 animCurrent(bounceidleanim),
79 animTarget(bounceidleanim),
86 howactive(typeactive),
88 superruntoggle(false),
89 lastattack(0), lastattack2(0), lastattack3(0),
90 currentoffset(), targetoffset(), offset(),
122 rabbitkickenabled(false),
131 damagetolerance(200),
134 superpermanentdamage(0),
148 bleedx(0), bleedy(0),
152 headyaw(0), headpitch(0),
153 targetheadyaw(0), targetheadpitch(0),
164 normalsupdatedelay(0),
167 forwardkeydown(false),
168 forwardstogglekeydown(false),
173 jumptogglekeydown(false),
174 crouchkeydown(false),
175 crouchtogglekeydown(false),
177 drawtogglekeydown(false),
179 throwtogglekeydown(false),
180 attackkeydown(false),
185 crouchkeydowntime(0),
199 whichdirection(false),
200 whichdirectiondelay(0),
201 avoidsomething(false),
210 lefthandmorphness(0),
211 righthandmorphness(0),
215 targetlefthandmorphness(0),
216 targetrighthandmorphness(0),
217 targetheadmorphness(1),
218 targetchestmorphness(0),
219 targettailmorphness(0),
220 lefthandmorphstart(0), lefthandmorphend(0),
221 righthandmorphstart(0), righthandmorphend(0),
222 headmorphstart(0), headmorphend(0),
223 chestmorphstart(0), chestmorphend(0),
224 tailmorphstart(0), tailmorphend(0),
227 highreversaldelay(0),
230 creature(rabbittype),
277 finalpathfindpoint(0),
278 targetpathfindpoint(0),
279 lastpathfindpoint(0),
280 lastpathfindpoint2(0),
281 lastpathfindpoint3(0),
282 lastpathfindpoint4(0),
299 neckspurtparticledelay(0),
303 rabbitkickragdoll(false),
311 /* Read a person in tfile. Throws an error if it’s not valid */
312 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
315 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
317 funpackf(tfile, "Bi", &howactive);
319 howactive = typeactive;
322 funpackf(tfile, "Bf", &scale);
327 funpackf(tfile, "Bb", &immobile);
332 funpackf(tfile, "Bf", &yaw);
337 if (num_weapons < 0 || num_weapons > 5) {
338 throw InvalidPersonException();
340 if (num_weapons > 0 && num_weapons < 5) {
341 for (int j = 0; j < num_weapons; j++) {
342 weaponids[j] = weapons.size();
344 funpackf(tfile, "Bi", &type);
345 weapons.push_back(Weapon(type, id));
348 funpackf(tfile, "Bi", &numwaypoints);
349 for (int j = 0; j < numwaypoints; j++) {
350 funpackf(tfile, "Bf", &waypoints[j].x);
351 funpackf(tfile, "Bf", &waypoints[j].y);
352 funpackf(tfile, "Bf", &waypoints[j].z);
354 funpackf(tfile, "Bi", &waypointtype[j]);
356 waypointtype[j] = wpkeepwalking;
360 funpackf(tfile, "Bi", &waypoint);
361 if (waypoint > (numwaypoints - 1)) {
365 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
366 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
367 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
368 funpackf(tfile, "Bf Bf", &power, &speedmult);
370 float headprop, legprop, armprop, bodyprop;
373 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
381 if (creature == wolftype) {
382 proportionhead = 1.1 * headprop;
383 proportionbody = 1.1 * bodyprop;
384 proportionarms = 1.1 * armprop;
385 proportionlegs = 1.1 * legprop;
386 } else if (creature == rabbittype) {
387 proportionhead = 1.2 * headprop;
388 proportionbody = 1.05 * bodyprop;
389 proportionarms = 1.00 * armprop;
390 proportionlegs = 1.1 * legprop;
391 proportionlegs.y = 1.05 * legprop;
394 funpackf(tfile, "Bi", &numclothes);
395 for (int k = 0; k < numclothes; k++) {
397 funpackf(tfile, "Bi", &templength);
398 for (int l = 0; l < templength; l++)
399 funpackf(tfile, "Bb", &clothes[k][l]);
400 clothes[k][templength] = '\0';
401 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
407 if (creature == wolftype) {
409 damagetolerance = 300;
416 realoldcoords = coords;
419 void Person::skeletonLoad(bool clothes)
422 if (creature != wolftype) {
424 "Skeleton/BasicFigure",
425 "Skeleton/BasicFigureLow",
426 "Skeleton/RabbitBelt",
428 "Models/Body2.solid",
429 "Models/Body3.solid",
430 "Models/Body4.solid",
431 "Models/Body5.solid",
432 "Models/Body6.solid",
433 "Models/Body7.solid",
434 "Models/BodyLow.solid",
440 "Skeleton/BasicFigureWolf",
441 "Skeleton/BasicFigureWolfLow",
442 "Skeleton/RabbitBelt",
444 "Models/Wolf2.solid",
445 "Models/Wolf3.solid",
446 "Models/Wolf4.solid",
447 "Models/Wolf5.solid",
448 "Models/Wolf6.solid",
449 "Models/Wolf7.solid",
450 "Models/WolfLow.solid",
456 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
462 * GameTick/doPlayerCollisions
464 void Person::CheckKick()
467 && (animTarget == rabbitkickanim
469 && victim != this->shared_from_this()
471 && animCurrent == rabbitkickanim)
472 && distsq(&coords, &victim->coords) < 1.2
473 && !victim->skeleton.free))
476 if (Animation::animations[victim->animTarget].height != lowheight) {
477 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
478 XYZ relative = velocity;
480 Normalise(&relative);
484 if (tutoriallevel != 1)
485 emit_sound_at(heavyimpactsound, victim->coords);
487 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
488 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
491 victim->DoDamage(100 * damagemult / victim->protectionhigh);
497 animTarget = backflipanim;
499 velocity = facing * -10;
503 resume_stream(whooshsound);
505 award_bonus(id, cannon);
506 } else if (victim->isCrouch()) {
507 animTarget = rabbitkickreversedanim;
508 animCurrent = rabbitkickreversedanim;
509 victim->animCurrent = rabbitkickreversalanim;
510 victim->animTarget = rabbitkickreversalanim;
516 victim->oldcoords = victim->coords;
517 coords = victim->coords;
518 victim->targetyaw = targetyaw;
519 victim->victim = this->shared_from_this();
526 * GameTick/doPlayerCollisions - spread fire between players
527 * GameTick/doDevKeys - press f to ignite
528 * Person::DoStuff - spread fire from lit campfires and bushes
530 void Person::CatchFire()
532 XYZ flatfacing, flatvelocity;
534 for (int i = 0; i < 10; i++) {
535 howmany = abs(Random() % (skeleton.joints.size()));
537 flatvelocity = skeleton.joints[howmany].velocity;
538 flatfacing = skeleton.joints[howmany].position * scale + coords;
540 flatvelocity = velocity;
541 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
543 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
548 emit_sound_at(firestartsound, coords);
550 emit_stream_at(stream_firesound, coords);
558 * idle animation for this creature (depending on status)
560 int Person::getIdle()
562 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
564 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
565 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
566 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
567 victim->id < Person::players.size())) {
568 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
569 if (creature == rabbittype)
570 return fightidleanim;
571 if (creature == wolftype)
574 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
575 if (weapons[weaponids[weaponactive]].getType() == knife)
576 return knifefightidleanim;
577 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
578 return swordfightidlebothanim;
579 if (weapons[weaponids[weaponactive]].getType() == sword)
580 return swordfightidleanim;
581 if (weapons[weaponids[weaponactive]].getType() == staff)
582 return swordfightidleanim;
584 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
585 return fightsidestep;
587 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
589 if (howactive == typesitting) return sitanim;
590 if (howactive == typesittingwall) return sitwallanim;
591 if (howactive == typesleeping) return sleepanim;
592 if (howactive == typedead1) return dead1anim;
593 if (howactive == typedead2) return dead2anim;
594 if (howactive == typedead3) return dead3anim;
595 if (howactive == typedead4) return dead4anim;
596 if (creature == rabbittype) return bounceidleanim;
597 if (creature == wolftype) return wolfidle;
602 * crouch animation for this creature
604 int Person::getCrouch()
606 if (creature == rabbittype)
608 if (creature == wolftype)
609 return wolfcrouchanim;
614 * running animation for this creature (can be upright or all fours)
618 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
620 if (creature == wolftype && (!superruntoggle))
623 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
624 return rabbitrunninganim;
625 if (creature == wolftype && (superruntoggle))
626 return wolfrunninganim;
632 int Person::getStop()
634 if (creature == rabbittype)
636 if (creature == wolftype)
643 int Person::getLanding()
645 if (creature == rabbittype)
647 if (creature == wolftype)
654 int Person::getLandhard()
656 if (creature == rabbittype)
658 if (creature == wolftype)
659 return wolflandhardanim;
666 * Person::DoAnimations
669 SolidHitBonus(int playerid)
671 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
672 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
674 award_bonus(playerid, solidhit);
678 * spawns blood effects
680 void Person::DoBlood(float howmuch, int which)
682 // FIXME: should abstract out inputs
683 static int bleedxint, bleedyint;
685 if (bloodtoggle && tutoriallevel != 1) {
686 if (bleeding <= 0 && spurt) {
688 for (int i = 0; i < 3; i++) {
689 // emit blood particles
692 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
693 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
694 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
695 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
698 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
699 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
700 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
701 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
704 if (Random() % 2 == 0) // 50% chance
705 for (int i = 0; i < 3; i++) {
706 if (Random() % 2 != 0) {
707 // emit teeth particles
710 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
711 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
714 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
715 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
719 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
721 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
723 Sprite::setLastSpriteSpecial(3); // sets it to teeth
728 // FIXME: manipulating attributes
729 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
732 if (creature == rabbittype)
733 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) {
734 bleedxint = abs(Random() % 512);
735 bleedyint = abs(Random() % 512);
737 if (creature == wolftype)
738 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) {
739 bleedxint = abs(Random() % 512);
740 bleedyint = abs(Random() % 512);
744 bleedy /= realtexdetail;
745 bleedx /= realtexdetail;
746 direction = abs(Random() % 2) * 2 - 1;
755 * spawns big blood effects and ???
756 * modifies character's skin texture
758 void Person::DoBloodBig(float howmuch, int which)
760 static int bleedxint, bleedyint, i, j;
762 if (howmuch && id == 0)
765 if (tutoriallevel != 1 || id == 0)
766 if (aitype != playercontrolled && howmuch > 0) {
770 if (creature == wolftype) {
771 int i = abs(Random() % 2);
773 whichsound = snarlsound;
775 whichsound = snarl2sound;
777 if (creature == rabbittype) {
778 int i = abs(Random() % 2);
780 whichsound = rabbitpainsound;
781 if (i == 1 && howmuch >= 2)
782 whichsound = rabbitpain1sound;
785 if (whichsound != -1) {
786 emit_sound_at(whichsound, coords);
791 if (id == 0 && howmuch > 0) {
795 if (bloodtoggle && decals && tutoriallevel != 1) {
796 if (bleeding <= 0 && spurt) {
798 for (int i = 0; i < 3; i++) {
799 // emit blood particles
800 // FIXME: copypaste from above
803 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
804 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
805 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
806 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
809 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
810 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
811 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
812 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
817 // weird texture manipulation code follows.
818 // looks like this is painting blood onto the character's skin texture
819 // FIXME: surely there's a better way
821 int offsetx = 0, offsety = 0;
823 offsety = Random() % 40;
824 offsetx = abs(Random() % 60);
826 if (which == 190 || which == 185) {
827 offsety = Random() % 40;
828 offsetx = abs(Random() % 100) - 20;
831 offsety = Random() % 10;
832 offsetx = Random() % 10;
835 offsety = Random() % 20;
836 offsetx = Random() % 20;
838 if (which == 220 || which == 215) {
848 if (creature == rabbittype)
849 for (i = 0; i < 512; i++) {
850 for (j = 0; j < 512; j++) {
851 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
852 if (i < startx) startx = i;
853 if (j < starty) starty = j;
854 if (i > endx) endx = i;
855 if (j > endy) endy = j;
859 if (creature == wolftype)
860 for (i = 0; i < 512; i++) {
861 for (j = 0; j < 512; j++) {
862 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
863 if (i < startx) startx = i;
864 if (j < starty) starty = j;
865 if (i > endx) endx = i;
866 if (j > endy) endy = j;
876 if (startx < 0) startx = 0;
877 if (starty < 0) starty = 0;
878 if (endx > 512 - 1) endx = 512 - 1;
879 if (endy > 512 - 1) endy = 512 - 1;
880 if (endx < startx) endx = startx;
881 if (endy < starty) endy = starty;
883 startx /= realtexdetail;
884 starty /= realtexdetail;
885 endx /= realtexdetail;
886 endy /= realtexdetail;
888 int texdetailint = realtexdetail;
890 if (creature == rabbittype)
891 for (i = startx; i < endx; i++) {
892 for (j = starty; j < endy; j++) {
893 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) {
894 color = Random() % 85 + 170;
895 where = i * skeleton.skinsize * 3 + j * 3;
896 if (skeleton.skinText[where + 0] > color / 2)
897 skeleton.skinText[where + 0] = color / 2;
898 skeleton.skinText[where + 1] = 0;
899 skeleton.skinText[where + 2] = 0;
903 if (creature == wolftype)
904 for (i = startx; i < endx; i++) {
905 for (j = starty; j < endy; j++) {
906 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) {
907 color = Random() % 85 + 170;
908 where = i * skeleton.skinsize * 3 + j * 3;
909 if (skeleton.skinText[where + 0] > color / 2)
910 skeleton.skinText[where + 0] = color / 2;
911 skeleton.skinText[where + 1] = 0;
912 skeleton.skinText[where + 2] = 0;
916 skeleton.drawmodel.textureptr.bind();
921 if (creature == rabbittype)
922 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) {
923 bleedxint = abs(Random() % 512);
924 bleedyint = abs(Random() % 512);
926 if (creature == wolftype)
927 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) {
928 bleedxint = abs(Random() % 512);
929 bleedyint = abs(Random() % 512);
931 bleedy = bleedxint + offsetx;
932 bleedx = bleedyint + offsety;
933 bleedy /= realtexdetail;
934 bleedx /= realtexdetail;
939 if (bleedx > skeleton.skinsize - 1)
940 bleedx = skeleton.skinsize - 1;
941 if (bleedy > skeleton.skinsize - 1)
942 bleedy = skeleton.skinsize - 1;
943 direction = abs(Random() % 2) * 2 - 1;
946 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
947 deathbleeding += bleeding;
948 bloodloss += bleeding * 3;
950 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
951 if (abs(Random() % 2) == 0) {
952 aitype = gethelptype;
955 aitype = attacktypecutoff;
963 * similar to DoBloodBig
965 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
969 static XYZ startpoint, endpoint, colpoint, movepoint;
970 static float rotationpoint;
972 static XYZ p1, p2, p3, p0;
975 float coordsx, coordsy;
978 if (bloodtoggle && decals && tutoriallevel != 1) {
981 where = DoRotation(where, 0, -yaw, 0);
989 // ray testing for a tri in the character model
990 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
991 if (whichtri != -1) {
992 // low level geometry math
994 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
995 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
996 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
998 bary.x = distsq(&p0, &p1);
999 bary.y = distsq(&p0, &p2);
1000 bary.z = distsq(&p0, &p3);
1002 total = bary.x + bary.y + bary.z;
1007 bary.x = 1 - bary.x;
1008 bary.y = 1 - bary.y;
1009 bary.z = 1 - bary.z;
1011 total = bary.x + bary.y + bary.z;
1017 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1018 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1019 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1020 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1021 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1022 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1023 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;
1024 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;
1026 if (bleeding <= 0 && spurt) {
1028 for (int i = 0; i < 3; i++) {
1029 // emit blood particles
1030 // FIXME: more copypaste code
1032 if (skeleton.free) {
1033 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1034 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1035 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1036 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1039 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1040 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1041 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1042 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1047 // texture manipulation follows
1049 int offsetx = 0, offsety = 0;
1050 offsetx = (1 + coordsy) * 512 - 291;
1051 offsety = coordsx * 512 - 437;
1058 if (creature == rabbittype)
1059 for (i = 0; i < 512; i++) {
1060 for (j = 0; j < 512; j++) {
1061 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1062 if (i < startx) startx = i;
1063 if (j < starty) starty = j;
1064 if (i > endx) endx = i;
1065 if (j > endy) endy = j;
1069 if (creature == wolftype)
1070 for (i = 0; i < 512; i++) {
1071 for (j = 0; j < 512; j++) {
1072 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1073 if (i < startx) startx = i;
1074 if (j < starty) starty = j;
1075 if (i > endx) endx = i;
1076 if (j > endy) endy = j;
1085 if (startx < 0) startx = 0;
1086 if (starty < 0) starty = 0;
1087 if (endx > 512 - 1) endx = 512 - 1;
1088 if (endy > 512 - 1) endy = 512 - 1;
1089 if (endx < startx) endx = startx;
1090 if (endy < starty) endy = starty;
1092 startx /= realtexdetail;
1093 starty /= realtexdetail;
1094 endx /= realtexdetail;
1095 endy /= realtexdetail;
1097 int texdetailint = realtexdetail;
1099 if (creature == rabbittype)
1100 for (i = startx; i < endx; i++) {
1101 for (j = starty; j < endy; j++) {
1102 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) {
1103 color = Random() % 85 + 170;
1104 where = i * skeleton.skinsize * 3 + j * 3;
1105 if (skeleton.skinText[where + 0] > color / 2)
1106 skeleton.skinText[where + 0] = color / 2;
1107 skeleton.skinText[where + 1] = 0;
1108 skeleton.skinText[where + 2] = 0;
1109 } 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) {
1110 color = Random() % 85 + 170;
1111 where = i * skeleton.skinsize * 3 + j * 3;
1112 if (skeleton.skinText[where + 0] > color / 2)
1113 skeleton.skinText[where + 0] = color / 2;
1114 skeleton.skinText[where + 1] = 0;
1115 skeleton.skinText[where + 2] = 0;
1119 if (creature == wolftype)
1120 for (i = startx; i < endx; i++) {
1121 for (j = starty; j < endy; j++) {
1122 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) {
1123 color = Random() % 85 + 170;
1124 where = i * skeleton.skinsize * 3 + j * 3;
1125 if (skeleton.skinText[where + 0] > color / 2)
1126 skeleton.skinText[where + 0] = color / 2;
1127 skeleton.skinText[where + 1] = 0;
1128 skeleton.skinText[where + 2] = 0;
1129 } 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) {
1130 color = Random() % 85 + 170;
1131 where = i * skeleton.skinsize * 3 + j * 3;
1132 if (skeleton.skinText[where + 0] > color / 2)
1133 skeleton.skinText[where + 0] = color / 2;
1134 skeleton.skinText[where + 1] = 0;
1135 skeleton.skinText[where + 2] = 0;
1139 skeleton.drawmodel.textureptr.bind();
1142 bleedy = (1 + coordsy) * 512;
1143 bleedx = coordsx * 512;
1144 bleedy /= realtexdetail;
1145 bleedx /= realtexdetail;
1150 if (bleedx > skeleton.skinsize - 1)
1151 bleedx = skeleton.skinsize - 1;
1152 if (bleedy > skeleton.skinsize - 1)
1153 bleedy = skeleton.skinsize - 1;
1154 direction = abs(Random() % 2) * 2 - 1;
1159 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1160 deathbleeding += bleeding;
1161 bloodloss += bleeding * 3;
1163 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1164 if (abs(Random() % 2) == 0) {
1165 aitype = gethelptype;
1168 aitype = attacktypecutoff;
1179 * guessing this performs a reversal
1181 void Person::Reverse()
1183 if (!((victim->aitype == playercontrolled
1185 || staggerdelay <= 0)
1186 && victim->animTarget != jumpupanim
1187 && victim->animTarget != jumpdownanim
1188 && (tutoriallevel != 1 || cananger)
1192 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1193 && (victim->id != 0 || difficulty >= 2)
1194 && (creature != wolftype || victim->creature == wolftype))
1197 if (animTarget == sweepanim) {
1198 animTarget = sweepreversedanim;
1199 animCurrent = sweepreversedanim;
1200 victim->animCurrent = sweepreversalanim;
1201 victim->animTarget = sweepreversalanim;
1203 if (animTarget == spinkickanim) {
1204 animTarget = spinkickreversedanim;
1205 animCurrent = spinkickreversedanim;
1206 victim->animCurrent = spinkickreversalanim;
1207 victim->animTarget = spinkickreversalanim;
1209 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1210 if (animTarget == rabbittacklinganim) {
1213 victim->frameCurrent = 6;
1214 victim->frameTarget = 7;
1216 animTarget = upunchreversedanim;
1217 animCurrent = upunchreversedanim;
1218 victim->animCurrent = upunchreversalanim;
1219 victim->animTarget = upunchreversalanim;
1221 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1222 if (victim->weaponactive != -1) {
1223 victim->throwtogglekeydown = 1;
1224 XYZ tempVelocity = victim->velocity * .2;
1225 if (tempVelocity.x == 0)
1226 tempVelocity.x = .1;
1227 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1228 victim->num_weapons--;
1229 if (victim->num_weapons) {
1230 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1231 if (victim->weaponstuck == victim->num_weapons)
1232 victim->weaponstuck = 0;
1235 victim->weaponactive = -1;
1236 for (unsigned j = 0; j < Person::players.size(); j++) {
1237 Person::players[j]->wentforweapon = 0;
1241 animTarget = staffhitreversedanim;
1242 animCurrent = staffhitreversedanim;
1243 victim->animCurrent = staffhitreversalanim;
1244 victim->animTarget = staffhitreversalanim;
1246 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1247 if (victim->weaponactive != -1) {
1248 victim->throwtogglekeydown = 1;
1249 XYZ tempVelocity = victim->velocity * .2;
1250 if (tempVelocity.x == 0)
1251 tempVelocity.x = .1;
1252 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1253 victim->num_weapons--;
1254 if (victim->num_weapons) {
1255 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1256 if (victim->weaponstuck == victim->num_weapons)
1257 victim->weaponstuck = 0;
1260 victim->weaponactive = -1;
1261 for (unsigned j = 0; j < Person::players.size(); j++) {
1262 Person::players[j]->wentforweapon = 0;
1265 animTarget = staffspinhitreversedanim;
1266 animCurrent = staffspinhitreversedanim;
1267 victim->animCurrent = staffspinhitreversalanim;
1268 victim->animTarget = staffspinhitreversalanim;
1270 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1271 if (victim->weaponactive != -1) {
1272 victim->throwtogglekeydown = 1;
1273 XYZ tempVelocity = victim->velocity * .2;
1274 if (tempVelocity.x == 0)
1275 tempVelocity.x = .1;
1276 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1277 victim->num_weapons--;
1278 if (victim->num_weapons) {
1279 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1280 if (victim->weaponstuck == victim->num_weapons)
1281 victim->weaponstuck = 0;
1284 victim->weaponactive = -1;
1285 for (unsigned j = 0; j < Person::players.size(); j++) {
1286 Person::players[j]->wentforweapon = 0;
1289 animTarget = swordslashreversedanim;
1290 animCurrent = swordslashreversedanim;
1291 victim->animCurrent = swordslashreversalanim;
1292 victim->animTarget = swordslashreversalanim;
1294 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1295 if (victim->weaponactive != -1) {
1296 victim->throwtogglekeydown = 1;
1297 XYZ tempVelocity = victim->velocity * .2;
1298 if (tempVelocity.x == 0)
1299 tempVelocity.x = .1;
1300 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1301 victim->num_weapons--;
1302 if (victim->num_weapons) {
1303 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1304 if (victim->weaponstuck == victim->num_weapons)
1305 victim->weaponstuck = 0;
1308 victim->weaponactive = -1;
1309 for (unsigned j = 0; j < Person::players.size(); j++) {
1310 Person::players[j]->wentforweapon = 0;
1313 animTarget = knifeslashreversedanim;
1314 animCurrent = knifeslashreversedanim;
1315 victim->animCurrent = knifeslashreversalanim;
1316 victim->animTarget = knifeslashreversalanim;
1318 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1319 victim->targettilt2 = targettilt2;
1320 victim->frameCurrent = frameCurrent;
1321 victim->frameTarget = frameTarget;
1322 victim->target = target;
1323 victim->velocity = 0;
1324 victim->oldcoords = victim->coords;
1325 victim->coords = coords;
1326 victim->targetyaw = targetyaw;
1327 victim->yaw = targetyaw;
1328 victim->victim = this->shared_from_this();
1330 if (animTarget == winduppunchanim) {
1331 animTarget = winduppunchblockedanim;
1332 victim->animTarget = blockhighleftanim;
1333 victim->frameTarget = 1;
1334 victim->target = .5;
1335 victim->victim = this->shared_from_this();
1336 victim->targetyaw = targetyaw + 180;
1338 if (animTarget == wolfslapanim) {
1339 animTarget = winduppunchblockedanim;
1340 victim->animTarget = blockhighleftanim;
1341 victim->frameTarget = 1;
1342 victim->target = .5;
1343 victim->victim = this->shared_from_this();
1344 victim->targetyaw = targetyaw + 180;
1346 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1347 animTarget = swordslashparriedanim;
1348 parriedrecently = .4;
1349 victim->parriedrecently = 0;
1350 victim->animTarget = swordslashparryanim;
1351 victim->frameTarget = 1;
1352 victim->target = .5;
1353 victim->victim = this->shared_from_this();
1354 victim->targetyaw = targetyaw + 180;
1356 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1357 if (victim->weaponactive != -1) {
1358 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1359 if (weapons[victim->weaponids[0]].getType() == staff)
1360 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1361 if (weapons[weaponids[0]].getType() == staff)
1362 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1363 emit_sound_at(swordstaffsound, victim->coords);
1365 emit_sound_at(metalhitsound, victim->coords);
1369 victim->Puff(righthand);
1371 victim->frameTarget = 0;
1372 victim->animTarget = staggerbackhighanim;
1373 victim->targetyaw = targetyaw + 180;
1375 aim = DoRotation(facing, 0, 90, 0) * 21;
1377 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1378 victim->num_weapons--;
1379 if (victim->num_weapons) {
1380 victim->weaponids[0] = victim->weaponids[num_weapons];
1381 if (victim->weaponstuck == victim->num_weapons)
1382 victim->weaponstuck = 0;
1384 victim->weaponactive = -1;
1385 for (unsigned i = 0; i < Person::players.size(); i++) {
1386 Person::players[i]->wentforweapon = 0;
1390 if (abs(Random() % 20) == 0) {
1391 if (weaponactive != -1) {
1392 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1393 if (weapons[victim->weaponids[0]].getType() == staff)
1394 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1395 if (weapons[weaponids[0]].getType() == staff)
1396 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1398 emit_sound_at(swordstaffsound, coords);
1400 emit_sound_at(metalhitsound, coords);
1408 animTarget = staggerbackhighanim;
1409 targetyaw = targetyaw + 180;
1411 aim = DoRotation(facing, 0, 90, 0) * 21;
1413 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1416 weaponids[0] = weaponids[num_weapons];
1417 if (weaponstuck == num_weapons)
1421 for (unsigned i = 0; i < Person::players.size(); i++) {
1422 Person::players[i]->wentforweapon = 0;
1429 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1430 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1431 victim->animTarget = dodgebackanim;
1432 victim->frameTarget = 0;
1436 rotatetarget = coords - victim->coords;
1437 Normalise(&rotatetarget);
1438 victim->targetyaw = -asin(0 - rotatetarget.x);
1439 victim->targetyaw *= 360 / 6.28;
1440 if (rotatetarget.z < 0)
1441 victim->targetyaw = 180 - victim->targetyaw;
1443 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1445 victim->lastattack3 = victim->lastattack2;
1446 victim->lastattack2 = victim->lastattack;
1447 victim->lastattack = victim->animTarget;
1449 victim->animTarget = sweepanim;
1450 victim->frameTarget = 0;
1454 rotatetarget = coords - victim->coords;
1455 Normalise(&rotatetarget);
1456 victim->targetyaw = -asin(0 - rotatetarget.x);
1457 victim->targetyaw *= 360 / 6.28;
1458 if (rotatetarget.z < 0)
1459 victim->targetyaw = 180 - victim->targetyaw;
1461 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1463 victim->lastattack3 = victim->lastattack2;
1464 victim->lastattack2 = victim->lastattack;
1465 victim->lastattack = victim->animTarget;
1470 victim->velocity = 0;
1472 if (aitype != playercontrolled) {
1474 if (escapednum < 2) {
1475 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1476 if ((Random() % chances) == 0) {
1482 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1489 void Person::DoDamage(float howmuch)
1491 // subtract health (temporary?)
1492 if (tutoriallevel != 1)
1493 damage += howmuch / power;
1496 damagedealt += howmuch / power;
1498 damagetaken += howmuch / power;
1501 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1504 if (tutoriallevel != 1)
1505 permanentdamage += howmuch / 2 / power;
1506 if (tutoriallevel != 1)
1507 superpermanentdamage += howmuch / 4 / power;
1509 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1511 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1515 camerashake += howmuch / 100;
1516 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1517 blackout = damage / damagetolerance;
1522 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1523 aitype = attacktypecutoff;
1524 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1525 if (abs(Random() % 2) == 0) {
1526 aitype = gethelptype;
1529 aitype = attacktypecutoff;
1533 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1536 for (int i = 0; i < skeleton.joints.size(); i++) {
1537 if (skeleton.free) {
1538 flatvelocity2 = skeleton.joints[i].velocity;
1539 flatfacing2 = skeleton.joints[i].position * scale + coords;
1541 flatvelocity2 = velocity;
1542 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1544 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1545 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1546 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1547 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1548 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1549 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1552 emit_sound_at(splattersound, coords);
1557 if (!dead && creature == wolftype) {
1558 award_bonus(0, Wolfbonus);
1565 if (tutoriallevel != 1 || id == 0)
1566 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1567 int whichsound = -1;
1569 if (creature == wolftype) {
1570 int i = abs(Random() % 2);
1572 whichsound = snarlsound;
1574 whichsound = snarl2sound;
1576 if (creature == rabbittype) {
1577 int i = abs(Random() % 2);
1579 whichsound = rabbitpainsound;
1580 if (i == 1 && damage > damagetolerance)
1581 whichsound = rabbitpain1sound;
1584 if (whichsound != -1) {
1585 emit_sound_at(whichsound, coords);
1586 addEnvSound(coords);
1593 * calculate/animate head facing direction?
1595 void Person::DoHead()
1597 static XYZ rotatearound;
1599 static float lookspeed = 500;
1601 if (!freeze && !winfreeze) {
1604 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1605 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1607 while (targetheadyaw > 180)targetheadyaw -= 360;
1608 while (targetheadyaw < -180)targetheadyaw += 360;
1610 if (targetheadyaw > 160)
1611 targetheadpitch = targetheadpitch * -1;
1612 if (targetheadyaw < -160)
1613 targetheadpitch = targetheadpitch * -1;
1614 if (targetheadyaw > 160)
1615 targetheadyaw = targetheadyaw - 180;
1616 if (targetheadyaw < -160)
1617 targetheadyaw = targetheadyaw + 180;
1619 if (targetheadpitch > 120)
1620 targetheadpitch = 120;
1621 if (targetheadpitch < -120)
1622 targetheadpitch = -120;
1623 if (targetheadyaw > 120)
1624 targetheadyaw = 120;
1625 if (targetheadyaw < -120)
1626 targetheadyaw = -120;
1629 targetheadpitch = 0;
1631 if (targetheadyaw > 80)
1633 if (targetheadyaw < -80)
1634 targetheadyaw = -80;
1635 if (targetheadpitch > 50)
1636 targetheadpitch = 50;
1637 if (targetheadpitch < -50)
1638 targetheadpitch = -50;
1641 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1642 headyaw = targetheadyaw;
1643 else if (headyaw > targetheadyaw) {
1644 headyaw -= multiplier * lookspeed;
1645 } else if (headyaw < targetheadyaw) {
1646 headyaw += multiplier * lookspeed;
1649 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1650 headpitch = targetheadpitch;
1651 else if (headpitch > targetheadpitch) {
1652 headpitch -= multiplier * lookspeed / 2;
1653 } else if (headpitch < targetheadpitch) {
1654 headpitch += multiplier * lookspeed / 2;
1657 rotatearound = jointPos(neck);
1658 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1662 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1663 facing = DoRotation(facing, headpitch * .4, 0, 0);
1664 facing = DoRotation(facing, 0, headyaw * .4, 0);
1667 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1668 facing = DoRotation(facing, headpitch * .8, 0, 0);
1669 facing = DoRotation(facing, 0, headyaw * .8, 0);
1672 if (animTarget == walkanim) {
1673 facing = DoRotation(facing, headpitch * .6, 0, 0);
1674 facing = DoRotation(facing, 0, headyaw * .6, 0);
1677 skeleton.specialforward[0] = facing;
1678 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1679 for (int i = 0; i < skeleton.muscles.size(); i++) {
1680 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1681 skeleton.FindRotationMuscle(i, animTarget);
1688 * ragdolls character?
1690 void Person::RagDoll(bool checkcollision)
1695 if (!skeleton.free) {
1698 if (id == 0 && isFlip())
1705 facing = DoRotation(facing, 0, yaw, 0);
1707 skeleton.freetime = 0;
1709 skeleton.longdead = 0;
1712 skeleton.broken = 0;
1713 skeleton.spinny = 1;
1715 skeleton.freefall = 1;
1717 if (!isnormal(velocity.x)) velocity.x = 0;
1718 if (!isnormal(velocity.y)) velocity.y = 0;
1719 if (!isnormal(velocity.z)) velocity.z = 0;
1720 if (!isnormal(yaw)) yaw = 0;
1721 if (!isnormal(coords.x)) coords = 0;
1722 if (!isnormal(tilt)) tilt = 0;
1723 if (!isnormal(tilt2)) tilt2 = 0;
1725 for (int i = 0; i < skeleton.joints.size(); i++) {
1726 skeleton.joints[i].delay = 0;
1727 skeleton.joints[i].locked = 0;
1728 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1729 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1730 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1731 skeleton.joints[i].position.y += .1;
1732 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1733 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1736 for (int i = 0; i < skeleton.joints.size(); i++) {
1737 skeleton.joints[i].velocity = 0;
1738 skeleton.joints[i].velchange = 0;
1740 skeleton.DoConstraints(&coords, &scale);
1741 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1742 skeleton.DoConstraints(&coords, &scale);
1743 skeleton.DoConstraints(&coords, &scale);
1744 skeleton.DoConstraints(&coords, &scale);
1745 skeleton.DoConstraints(&coords, &scale);
1748 speed = targetFrame().speed * 2;
1749 if (currentFrame().speed > targetFrame().speed) {
1750 speed = currentFrame().speed * 2;
1753 speed = transspeed * 2;
1757 for (int i = 0; i < skeleton.joints.size(); i++) {
1758 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1759 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((targetFrame().joints[i].position - currentFrame().joints[i].position) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1761 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1762 change.x = (float)(Random() % 100) / 100;
1763 change.y = (float)(Random() % 100) / 100;
1764 change.z = (float)(Random() % 100) / 100;
1765 skeleton.joints[i].velocity += change;
1766 skeleton.joints[abs(Random() % skeleton.joints.size())].velocity -= change;
1768 change.x = (float)(Random() % 100) / 100;
1769 change.y = (float)(Random() % 100) / 100;
1770 change.z = (float)(Random() % 100) / 100;
1771 skeleton.joints[i].velchange += change;
1772 skeleton.joints[abs(Random() % skeleton.joints.size())].velchange -= change;
1775 if (checkcollision) {
1782 for (j = 0; j < skeleton.joints.size(); j++) {
1783 average += skeleton.joints[j].position;
1787 coords += average * scale;
1788 for (j = 0; j < skeleton.joints.size(); j++) {
1789 skeleton.joints[j].position -= average;
1792 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1793 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1794 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1795 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1796 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1799 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1800 coords.x = lowpoint.x;
1801 coords.z = lowpoint.z;
1810 for (int i = 0; i < skeleton.joints.size(); i++) {
1811 velocity += skeleton.joints[i].velocity * scale;
1813 velocity /= skeleton.joints.size();
1816 if (Random() % 2 == 0) {
1817 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1818 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1819 weapons[weaponids[0]].velocity.x += .01;
1822 weaponids[0] = weaponids[num_weapons];
1823 if (weaponstuck == num_weapons)
1827 for (unsigned i = 0; i < Person::players.size(); i++) {
1828 Person::players[i]->wentforweapon = 0;
1833 animTarget = bounceidleanim;
1834 animCurrent = bounceidleanim;
1844 void Person::FootLand(bodypart whichfoot, float opacity)
1846 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1847 cerr << "FootLand called on wrong bodypart" << endl;
1850 static XYZ terrainlight;
1851 static XYZ footvel, footpoint;
1852 if (opacity >= 1 || skiddelay <= 0) {
1855 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1856 if (distsq(&footpoint, &viewer))
1857 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1858 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1859 footvel = velocity / 5;
1862 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1863 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1864 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1865 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1866 if (environment == snowyenvironment) {
1867 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1869 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1871 } else if (environment == grassyenvironment) {
1872 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1873 } else if (environment == desertenvironment) {
1874 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1876 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1880 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1881 footvel = velocity / 5;
1884 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1885 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1886 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1893 * make a puff effect at a body part (dust effect?)
1895 void Person::Puff(int whichlabel)
1897 static XYZ footvel, footpoint;
1900 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1901 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1905 * I think I added this in an attempt to clean up code
1907 void Person::setAnimation(int animation)
1909 animTarget = animation;
1918 void Person::DoAnimations()
1920 if (!skeleton.free) {
1921 static float oldtarget;
1923 if (isIdle() && animCurrent != getIdle())
1924 normalsupdatedelay = 0;
1926 if (animTarget == tempanim || animCurrent == tempanim) {
1927 Animation::animations[tempanim] = tempanimation;
1929 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1935 vel[0] = velocity.x;
1936 vel[1] = velocity.y;
1937 vel[2] = velocity.z;
1940 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1941 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1943 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1945 if (!crouchkeydown && velocity.y >= -15)
1948 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1953 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1955 if (normaldotproduct(targfacing, velocity) >= -.3)
1956 animTarget = flipanim;
1958 animTarget = backflipanim;
1959 crouchtogglekeydown = 1;
1967 if (Animation::animations[animTarget].attack != reversed)
1969 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1970 crouchtogglekeydown = 0;
1971 if (aitype == playercontrolled)
1974 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1977 crouchtogglekeydown = 1;
1981 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1983 normalsupdatedelay = 0;
1987 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1989 emit_sound_at(fireendsound, coords);
1990 pause_sound(stream_firesound);
1994 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1995 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1997 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1998 if (normaldotproduct(victim->facing, facing) > 0)
1999 victim->animTarget = rabbittackledbackanim;
2001 victim->animTarget = rabbittackledfrontanim;
2002 victim->frameTarget = 2;
2005 victim->targetyaw = yaw;
2006 if (victim->aitype == gethelptype)
2007 victim->DoDamage(victim->damagetolerance - victim->damage);
2008 //victim->DoDamage(30);
2009 if (creature == wolftype) {
2011 emit_sound_at(clawslicesound, victim->coords);
2013 victim->DoBloodBig(1 / victim->armorhead, 210);
2015 award_bonus(id, TackleBonus,
2016 victim->aitype == gethelptype ? 50 : 0);
2020 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2021 if (weapons[weaponids[0]].getType() == knife) {
2022 if (weaponactive == -1)
2024 else if (weaponactive == 0)
2027 if (weaponactive == -1) {
2028 emit_sound_at(knifesheathesound, coords);
2030 if (weaponactive != -1) {
2031 emit_sound_at(knifedrawsound, coords, 128);
2034 drawtogglekeydown = 1;
2037 if (tutoriallevel != 1 || id == 0)
2038 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2041 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2042 if (targetFrame().label == 1)
2043 whichsound = footstepsound;
2045 whichsound = footstepsound2;
2046 if (targetFrame().label == 1)
2047 FootLand(leftfoot, 1);
2048 if (targetFrame().label == 2)
2049 FootLand(rightfoot, 1);
2050 if (targetFrame().label == 3 && isRun()) {
2051 FootLand(rightfoot, 1);
2052 FootLand(leftfoot, 1);
2056 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2057 if (targetFrame().label == 1)
2058 whichsound = footstepsound3;
2060 whichsound = footstepsound4;
2064 if (targetFrame().label == 1)
2065 whichsound = footstepsound3;
2067 whichsound = footstepsound4;
2069 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2070 if (Animation::animations[animTarget].attack != neutral) {
2071 unsigned r = abs(Random() % 3);
2073 whichsound = lowwhooshsound;
2075 whichsound = midwhooshsound;
2077 whichsound = highwhooshsound;
2079 if (Animation::animations[animTarget].attack == neutral)
2080 whichsound = movewhooshsound;
2081 } else if (targetFrame().label == 4)
2082 whichsound = knifeswishsound;
2083 if (targetFrame().label == 8 && tutoriallevel != 1)
2084 whichsound = landsound2;
2086 emit_sound_at(whichsound, coords, 256.);
2089 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2090 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2091 addEnvSound(coords, 15);
2093 addEnvSound(coords, 6);
2097 if (targetFrame().label == 3) {
2099 emit_sound_at(whichsound, coords, 128.);
2104 if (tutoriallevel != 1 || id == 0)
2105 if (speechdelay <= 0)
2106 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2107 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2108 int whichsound = -1;
2109 if (targetFrame().label == 4 && aitype != playercontrolled) {
2110 if (Animation::animations[animTarget].attack != neutral) {
2111 unsigned r = abs(Random() % 4);
2112 if (creature == rabbittype) {
2113 if (r == 0) whichsound = rabbitattacksound;
2114 if (r == 1) whichsound = rabbitattack2sound;
2115 if (r == 2) whichsound = rabbitattack3sound;
2116 if (r == 3) whichsound = rabbitattack4sound;
2118 if (creature == wolftype) {
2119 if (r == 0) whichsound = barksound;
2120 if (r == 1) whichsound = bark2sound;
2121 if (r == 2) whichsound = bark3sound;
2122 if (r == 3) whichsound = barkgrowlsound;
2128 if (whichsound != -1) {
2129 emit_sound_at(whichsound, coords);
2135 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2136 FootLand(leftfoot, 1);
2137 FootLand(rightfoot, 1);
2141 currentoffset = targetoffset;
2142 frameTarget = frameCurrent;
2143 animCurrent = animTarget;
2146 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2147 for (unsigned i = 0; i < weapons.size(); i++) {
2148 if (weapons[i].owner == -1)
2149 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2150 if (distsq(&coords, &weapons[i].position) >= 1) {
2151 if (weapons[i].getType() != staff) {
2152 emit_sound_at(knifedrawsound, coords, 128.);
2161 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2162 for (unsigned i = 0; i < weapons.size(); i++) {
2163 bool willwork = true;
2164 if (weapons[i].owner != -1)
2165 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2166 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2167 if (Person::players[weapons[i].owner]->num_weapons > 1)
2169 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2170 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2171 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2172 bool fleshstuck = false;
2173 if (weapons[i].owner != -1)
2174 if (victim->weaponstuck != -1) {
2175 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2180 emit_sound_at(fleshstabremovesound, coords, 128.);
2182 if (weapons[i].getType() != staff) {
2183 emit_sound_at(knifedrawsound, coords, 128.);
2186 if (weapons[i].owner != -1) {
2187 victim = Person::players[weapons[i].owner];
2188 if (victim->num_weapons == 1)
2189 victim->num_weapons = 0;
2191 victim->num_weapons = 1;
2193 //victim->weaponactive=-1;
2194 victim->skeleton.longdead = 0;
2195 victim->skeleton.free = 1;
2196 victim->skeleton.broken = 0;
2198 for (int j = 0; j < victim->skeleton.joints.size(); j++) {
2199 victim->skeleton.joints[j].velchange = 0;
2200 victim->skeleton.joints[j].locked = 0;
2206 Normalise(&relative);
2207 XYZ footvel, footpoint;
2209 footpoint = weapons[i].position;
2210 if (victim->weaponstuck != -1) {
2211 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2213 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2214 weapons[i].bloody = 2;
2215 weapons[i].blooddrip = 5;
2216 victim->weaponstuck = -1;
2219 if (victim->num_weapons > 0) {
2220 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2221 victim->weaponstuck = 0;
2222 if (victim->weaponids[0] == int(i))
2223 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2226 victim->jointVel(abdomen) += relative * 6;
2227 victim->jointVel(neck) += relative * 6;
2228 victim->jointVel(rightshoulder) += relative * 6;
2229 victim->jointVel(leftshoulder) += relative * 6;
2237 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2238 if (weaponactive == -1)
2240 else if (weaponactive == 0) {
2242 if (num_weapons == 2) {
2244 buffer = weaponids[0];
2245 weaponids[0] = weaponids[1];
2246 weaponids[1] = buffer;
2249 if (weaponactive == -1) {
2250 emit_sound_at(knifesheathesound, coords, 128.);
2252 if (weaponactive != -1) {
2253 emit_sound_at(knifedrawsound, coords, 128.);
2258 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2259 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2260 Normalise(&rotatetarget);
2261 targetyaw = -asin(0 - rotatetarget.x);
2262 targetyaw *= 360 / 6.28;
2263 if (rotatetarget.z < 0)
2264 targetyaw = 180 - targetyaw;
2266 if (animTarget == walljumprightkickanim)
2268 if (animTarget == walljumpleftkickanim)
2274 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2277 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2282 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2283 animTarget = rabbittackleanim;
2285 emit_sound_at(jumpsound, coords);
2293 targetloc = velocity;
2294 Normalise(&targetloc);
2295 targetloc += coords;
2296 for (unsigned i = 0; i < Person::players.size(); i++) {
2298 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2299 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2303 if (closestid != -1)
2304 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2306 victim = Person::players[closestid];
2307 coords = victim->coords;
2308 animCurrent = rabbittacklinganim;
2309 animTarget = rabbittacklinganim;
2313 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2314 rotatetarget = coords - victim->coords;
2315 Normalise(&rotatetarget);
2316 targetyaw = -asin(0 - rotatetarget.x);
2317 targetyaw *= 360 / 6.28;
2318 if (rotatetarget.z < 0)
2319 targetyaw = 180 - targetyaw;
2321 if (animTarget != rabbitrunninganim) {
2322 emit_sound_at(jumpsound, coords, 128.);
2328 float damagemult = 1 * power;
2329 if (creature == wolftype)
2330 damagemult = 2.5 * power;
2332 damagemult /= victim->damagetolerance / 200;
2334 if ((Animation::animations[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2335 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2336 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2340 if (Random() % 2 || creature == wolftype) {
2343 if (creature == wolftype)
2346 if (tutoriallevel != 1) {
2347 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2349 if (creature == wolftype) {
2350 emit_sound_at(clawslicesound, victim->coords, 128.);
2352 victim->DoBloodBig(2 / victim->armorhead, 175);
2356 relative = victim->coords - coords;
2358 Normalise(&relative);
2359 relative = DoRotation(relative, 0, -90, 0);
2360 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2361 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2363 victim->jointVel(head) += relative * damagemult * 200;
2365 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2371 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2372 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2376 if (Random() % 2 || creature == wolftype) {
2378 if (creature == wolftype)
2381 emit_sound_at(whooshhitsound, victim->coords);
2382 if (creature == wolftype) {
2383 emit_sound_at(clawslicesound, victim->coords, 128.);
2385 victim->DoBloodBig(2, 175);
2389 relative = victim->coords - coords;
2391 Normalise(&relative);
2393 Normalise(&relative);
2394 relative = DoRotation(relative, 0, 90, 0);
2395 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2396 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2398 victim->jointVel(head) += relative * damagemult * 100;
2400 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2404 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2405 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2411 if (tutoriallevel != 1) {
2412 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2414 if (creature == wolftype) {
2415 emit_sound_at(clawslicesound, victim->coords, 128.);
2417 victim->DoBloodBig(2 / victim->armorhead, 175);
2423 Normalise(&relative);
2424 relative = DoRotation(relative, 0, -90, 0);
2425 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2426 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2428 victim->jointVel(head) += relative * damagemult * 200;
2430 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2432 if (victim->damage > victim->damagetolerance)
2433 award_bonus(id, style);
2439 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2440 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2446 if (tutoriallevel != 1) {
2447 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2449 if (creature == wolftype) {
2450 emit_sound_at(clawslicesound, victim->coords, 128.);
2452 victim->DoBloodBig(2 / victim->armorhead, 175);
2458 Normalise(&relative);
2459 relative = DoRotation(relative, 0, 90, 0);
2460 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2461 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2463 victim->jointVel(head) += relative * damagemult * 200;
2465 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2467 if (victim->damage > victim->damagetolerance)
2468 award_bonus(id, style);
2474 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2475 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2483 emit_sound_at(whooshhitsound, victim->coords);
2486 relative = victim->coords - coords;
2488 Normalise(&relative);
2489 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2490 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2492 victim->jointVel(head) += relative * damagemult * 100;
2494 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2498 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2499 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2503 emit_sound_at(whooshhitsound, victim->coords, 128.);
2505 victim->skeleton.longdead = 0;
2506 victim->skeleton.free = 1;
2507 victim->skeleton.broken = 0;
2508 victim->skeleton.spinny = 1;
2510 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2511 victim->skeleton.joints[i].velchange = 0;
2512 victim->skeleton.joints[i].delay = 0;
2513 victim->skeleton.joints[i].locked = 0;
2514 //victim->skeleton.joints[i].velocity=0;
2520 Normalise(&relative);
2521 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2522 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2523 victim->skeleton.joints[i].position.y += relative.y * .3;
2524 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2525 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2527 victim->Puff(abdomen);
2528 victim->jointVel(abdomen).y = relative.y * 400;
2532 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2533 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2537 if (tutoriallevel != 1) {
2538 emit_sound_at(heavyimpactsound, coords, 128.);
2541 relative = victim->coords - coords;
2543 Normalise(&relative);
2544 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2545 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2547 victim->Puff(abdomen);
2548 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2552 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2553 victim->jointVel(abdomen) += relative * damagemult * 300;
2557 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2558 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2562 if (tutoriallevel != 1) {
2563 emit_sound_at(thudsound, coords);
2566 victim->skeleton.longdead = 0;
2567 victim->skeleton.free = 1;
2568 victim->skeleton.broken = 0;
2569 victim->skeleton.spinny = 1;
2571 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2572 victim->skeleton.joints[i].velchange = 0;
2573 //victim->skeleton.joints[i].delay=0;
2574 victim->skeleton.joints[i].locked = 0;
2577 relative = victim->coords - coords;
2578 Normalise(&relative);
2580 Normalise(&relative);
2581 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2582 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2587 victim->Puff(abdomen);
2588 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2589 victim->jointVel(abdomen) += relative * damagemult * 200;
2598 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2601 if (!victim->skeleton.free)
2605 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2606 emit_sound_at(knifesheathesound, coords, 128.);
2609 if (victim && hasvictim) {
2610 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2612 XYZ where, startpoint, endpoint, movepoint, colpoint;
2613 float rotationpoint;
2615 if (weapons[weaponids[weaponactive]].getType() == knife) {
2616 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2617 where -= victim->coords;
2618 if (!victim->skeleton.free)
2619 where = DoRotation(where, 0, -victim->yaw, 0);
2622 startpoint.y += 100;
2626 if (weapons[weaponids[weaponactive]].getType() == sword) {
2627 where = weapons[weaponids[weaponactive]].position;
2628 where -= victim->coords;
2629 if (!victim->skeleton.free)
2630 where = DoRotation(where, 0, -victim->yaw, 0);
2632 where = weapons[weaponids[weaponactive]].tippoint;
2633 where -= victim->coords;
2634 if (!victim->skeleton.free)
2635 where = DoRotation(where, 0, -victim->yaw, 0);
2638 if (weapons[weaponids[weaponactive]].getType() == staff) {
2639 where = weapons[weaponids[weaponactive]].position;
2640 where -= victim->coords;
2641 if (!victim->skeleton.free)
2642 where = DoRotation(where, 0, -victim->yaw, 0);
2644 where = weapons[weaponids[weaponactive]].tippoint;
2645 where -= victim->coords;
2646 if (!victim->skeleton.free)
2647 where = DoRotation(where, 0, -victim->yaw, 0);
2652 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2654 if (whichtri != -1) {
2655 if (victim->dead != 2) {
2656 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2658 award_bonus(id, FinishedBonus);
2661 weapons[weaponids[weaponactive]].bloody = 2;
2663 victim->skeleton.longdead = 0;
2664 victim->skeleton.free = 1;
2665 victim->skeleton.broken = 0;
2667 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2668 victim->skeleton.joints[i].velchange = 0;
2669 victim->skeleton.joints[i].locked = 0;
2670 //victim->skeleton.joints[i].velocity=0;
2672 emit_sound_at(fleshstabsound, coords, 128);
2675 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2676 weapons[weaponids[weaponactive]].blooddrip += 5;
2677 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2679 if (whichtri == -1) {
2681 emit_sound_at(knifesheathesound, coords, 128.);
2687 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2689 emit_sound_at(knifedrawsound, coords, 128);
2692 if (victim && hasvictim) {
2693 XYZ footvel, footpoint;
2695 emit_sound_at(fleshstabremovesound, coords, 128.);
2698 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2700 if (weapons[weaponids[weaponactive]].getType() == sword) {
2701 XYZ where, startpoint, endpoint, movepoint;
2702 float rotationpoint;
2705 where = weapons[weaponids[weaponactive]].position;
2706 where -= victim->coords;
2707 if (!victim->skeleton.free)
2708 where = DoRotation(where, 0, -victim->yaw, 0);
2710 where = weapons[weaponids[weaponactive]].tippoint;
2711 where -= victim->coords;
2712 if (!victim->skeleton.free)
2713 where = DoRotation(where, 0, -victim->yaw, 0);
2718 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2719 footpoint += victim->coords;
2721 if (whichtri == -1) {
2722 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2725 if (weapons[weaponids[weaponactive]].getType() == staff) {
2726 XYZ where, startpoint, endpoint, movepoint;
2727 float rotationpoint;
2730 where = weapons[weaponids[weaponactive]].position;
2731 where -= victim->coords;
2732 if (!victim->skeleton.free)
2733 where = DoRotation(where, 0, -victim->yaw, 0);
2735 where = weapons[weaponids[weaponactive]].tippoint;
2736 where -= victim->coords;
2737 if (!victim->skeleton.free)
2738 where = DoRotation(where, 0, -victim->yaw, 0);
2743 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2744 footpoint += victim->coords;
2746 if (whichtri == -1) {
2747 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2750 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2752 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2753 victim->skeleton.longdead = 0;
2754 victim->skeleton.free = 1;
2755 victim->skeleton.broken = 0;
2757 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2758 victim->skeleton.joints[i].velchange = 0;
2759 victim->skeleton.joints[i].locked = 0;
2760 //victim->skeleton.joints[i].velocity=0;
2766 Normalise(&relative);
2767 //victim->Puff(abdomen);
2769 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2771 if (victim->bloodloss < victim->damagetolerance) {
2772 victim->bloodloss += 1000;
2776 victim->jointVel(abdomen) += relative * damagemult * 20;
2780 if (!hasvictim && onterrain) {
2781 weapons[weaponids[weaponactive]].bloody = 0;
2782 weapons[weaponids[weaponactive]].blooddrip = 0;
2786 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2787 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2795 if (tutoriallevel != 1) {
2796 emit_sound_at(heavyimpactsound, victim->coords, 128);
2801 relative = victim->coords - coords;
2803 Normalise(&relative);
2804 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2805 victim->skeleton.joints[i].velocity = relative * 30;
2807 victim->jointVel(head) += relative * damagemult * 150;
2809 victim->frameTarget = 0;
2810 victim->animTarget = staggerbackhardanim;
2811 victim->targetyaw = targetyaw + 180;
2813 victim->stunned = 1;
2816 victim->Puff(abdomen);
2817 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2824 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2825 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2829 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2830 if (tutoriallevel != 1) {
2831 emit_sound_at(thudsound, victim->coords);
2833 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2834 if (tutoriallevel != 1) {
2835 emit_sound_at(whooshhitsound, victim->coords);
2838 if (tutoriallevel != 1) {
2839 emit_sound_at(heavyimpactsound, victim->coords);
2843 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2846 relative = victim->coords - coords;
2848 Normalise(&relative);
2850 Normalise(&relative);
2851 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2852 victim->skeleton.joints[i].velocity = relative * 5;
2854 victim->jointVel(abdomen) += relative * damagemult * 400;
2856 victim->frameTarget = 0;
2857 victim->animTarget = staggerbackhardanim;
2858 victim->targetyaw = targetyaw + 180;
2860 victim->stunned = 1;
2862 victim->Puff(abdomen);
2863 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2869 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2870 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2871 if (victim->id == 0)
2873 emit_sound_at(landsound2, victim->coords);
2879 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2880 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2881 if (victim->id == 0)
2884 if (weaponactive != -1) {
2885 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2886 if (weapons[victim->weaponids[0]].getType() == staff)
2887 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2888 if (weapons[weaponids[0]].getType() == staff)
2889 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2891 emit_sound_at(swordstaffsound, victim->coords);
2893 emit_sound_at(metalhitsound, victim->coords);
2901 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2902 if (weaponactive != -1) {
2905 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);
2907 weapons[weaponids[0]].thrown(aim * 50);
2910 weaponids[0] = weaponids[num_weapons];
2916 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2918 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2920 if (tutoriallevel != 1)
2921 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2923 award_bonus(id, Slicebonus);
2924 if (tutoriallevel != 1) {
2925 emit_sound_at(knifeslicesound, victim->coords);
2927 //victim->jointVel(abdomen)+=relative*damagemult*200;
2928 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2929 if (victim->id != 0 || difficulty == 2) {
2930 victim->frameTarget = 0;
2931 victim->animTarget = staggerbackhardanim;
2932 victim->targetyaw = targetyaw + 180;
2936 victim->lowreversaldelay = 0;
2937 victim->highreversaldelay = 0;
2938 if (aitype != playercontrolled)
2939 weaponmissdelay = .6;
2941 if (tutoriallevel != 1)
2942 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2943 weapons[weaponids[weaponactive]].bloody = 1;
2944 if (tutoriallevel != 1)
2945 weapons[weaponids[weaponactive]].blooddrip += 3;
2947 XYZ footvel, footpoint;
2949 if (skeleton.free) {
2950 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2952 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2954 if (tutoriallevel != 1) {
2956 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2957 footvel = DoRotation(facing, 0, 90, 0) * .8;
2959 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2960 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2961 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2962 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2964 if (tutoriallevel == 1) {
2965 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2967 victim->DoDamage(damagemult * 0);
2970 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2971 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2972 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2973 award_bonus(id, Slashbonus);
2975 if (tutoriallevel != 1) {
2976 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2977 victim->DoBloodBig(2 / victim->armorhigh, 190);
2979 victim->DoBloodBig(2 / victim->armorhigh, 185);
2980 victim->deathbleeding = 1;
2981 emit_sound_at(swordslicesound, victim->coords);
2983 //victim->jointVel(abdomen)+=relative*damagemult*200;
2984 if (tutoriallevel != 1) {
2985 victim->frameTarget = 0;
2986 victim->animTarget = staggerbackhardanim;
2987 victim->targetyaw = targetyaw + 180;
2991 if (tutoriallevel != 1) {
2992 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2993 weapons[weaponids[weaponactive]].bloody = 1;
2994 weapons[weaponids[weaponactive]].blooddrip += 3;
2996 float bloodlossamount;
2997 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2998 victim->bloodloss += bloodlossamount / victim->armorhigh;
2999 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
3000 victim->DoDamage(damagemult * 0);
3002 XYZ footvel, footpoint;
3004 if (skeleton.free) {
3005 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3007 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3010 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3011 footvel = DoRotation(facing, 0, 90, 0) * .8;
3013 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3014 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3015 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3016 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3019 if (victim->weaponactive != -1) {
3020 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3021 if (weapons[victim->weaponids[0]].getType() == staff)
3022 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3023 if (weapons[weaponids[0]].getType() == staff)
3024 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3026 emit_sound_at(swordstaffsound, victim->coords);
3028 emit_sound_at(metalhitsound, victim->coords);
3034 victim->Puff(righthand);
3036 victim->frameTarget = 0;
3037 victim->animTarget = staggerbackhighanim;
3038 victim->targetyaw = targetyaw + 180;
3040 aim = DoRotation(facing, 0, 90, 0) * 21;
3042 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3043 victim->num_weapons--;
3044 if (victim->num_weapons) {
3045 victim->weaponids[0] = victim->weaponids[num_weapons];
3046 if (victim->weaponstuck == victim->num_weapons)
3047 victim->weaponstuck = 0;
3049 victim->weaponactive = -1;
3050 for (unsigned i = 0; i < Person::players.size(); i++) {
3051 Person::players[i]->wentforweapon = 0;
3058 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3059 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3060 if (tutoriallevel != 1) {
3061 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3065 if (Random() % 2 || creature == wolftype) {
3068 emit_sound_at(staffheadsound, victim->coords);
3072 relative = victim->coords - coords;
3074 Normalise(&relative);
3075 relative = DoRotation(relative, 0, 90, 0);
3077 Normalise(&relative);
3078 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3079 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3081 victim->jointVel(head) += relative * damagemult * 230;
3082 victim->jointVel(neck) += relative * damagemult * 230;
3084 if (tutoriallevel != 1) {
3085 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3087 award_bonus(id, solidhit, 30);
3092 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3093 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3094 if (tutoriallevel != 1) {
3095 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3099 if (Random() % 2 || creature == wolftype) {
3102 emit_sound_at(staffheadsound, victim->coords);
3106 relative = victim->coords - coords;
3108 Normalise(&relative);
3109 relative = DoRotation(relative, 0, -90, 0);
3110 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3111 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3113 victim->jointVel(head) += relative * damagemult * 220;
3114 victim->jointVel(neck) += relative * damagemult * 220;
3116 if (tutoriallevel != 1) {
3117 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3119 award_bonus(id, solidhit, 60);
3124 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3125 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3127 if (tutoriallevel != 1) {
3129 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3132 if (Random() % 2 || creature == wolftype) {
3135 emit_sound_at(staffbodysound, victim->coords);
3137 victim->skeleton.longdead = 0;
3138 victim->skeleton.free = 1;
3139 victim->skeleton.broken = 0;
3141 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3142 victim->skeleton.joints[i].velchange = 0;
3143 victim->skeleton.joints[i].locked = 0;
3144 //victim->skeleton.joints[i].velocity=0;
3151 Normalise(&relative);
3152 if (!victim->dead) {
3153 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3154 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3156 victim->jointVel(abdomen) += relative * damagemult * 40;
3159 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3160 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3163 victim->Puff(abdomen);
3164 if (tutoriallevel != 1) {
3165 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3167 if (!victim->dead) {
3168 award_bonus(id, solidhit, 40);
3174 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3175 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3180 relative = victim->coords - coords;
3182 Normalise(&relative);
3186 if (Animation::animations[victim->animTarget].height == lowheight) {
3192 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3193 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3195 victim->jointVel(head) += relative * damagemult * 200;
3196 if (tutoriallevel != 1) {
3197 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3200 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3201 if (victim->howactive == typesleeping)
3202 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3203 if (creature == wolftype) {
3204 emit_sound_at(clawslicesound, victim->coords, 128.);
3206 victim->DoBloodBig(2 / victim->armorhead, 175);
3209 if (victim->damage >= victim->damagetolerance)
3211 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3212 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3214 victim->jointVel(abdomen) += relative * damagemult * 200;
3215 victim->frameTarget = 0;
3216 victim->animTarget = staggerbackhighanim;
3217 victim->targetyaw = targetyaw + 180;
3219 if (tutoriallevel != 1) {
3220 emit_sound_at(landsound2, victim->coords, 128.);
3222 victim->Puff(abdomen);
3223 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3224 if (creature == wolftype) {
3225 emit_sound_at(clawslicesound, victim->coords, 128.);
3227 victim->DoBloodBig(2 / victim->armorhigh, 170);
3234 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3235 if ((victim->animTarget != jumpupanim) &&
3236 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3237 (victim != this->shared_from_this())) {
3241 if (tutoriallevel != 1) {
3242 emit_sound_at(landsound2, victim->coords, 128.);
3245 relative = victim->coords - coords;
3247 Normalise(&relative);
3249 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3252 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3253 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3255 relative = DoRotation(relative, 0, -90, 0);
3257 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3258 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)
3259 victim->skeleton.joints[i].velocity = relative * 80;
3261 victim->Puff(rightankle);
3262 victim->Puff(leftankle);
3263 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3265 if (victim->damage >= victim->damagetolerance)
3267 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3268 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3270 relative = DoRotation(relative, 0, -90, 0);
3271 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3272 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)
3273 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3275 victim->jointVel(abdomen) += relative * damagemult * 200;
3276 victim->frameTarget = 0;
3277 victim->animTarget = staggerbackhighanim;
3278 victim->targetyaw = targetyaw + 180;
3280 if (tutoriallevel != 1) {
3281 emit_sound_at(landsound2, victim->coords, 128.);
3283 victim->Puff(abdomen);
3284 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3292 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3293 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3301 if (tutoriallevel != 1) {
3302 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3304 if (creature == wolftype) {
3305 emit_sound_at(clawslicesound, victim->coords, 128);
3307 victim->DoBloodBig(2 / victim->armorhigh, 170);
3311 relative = victim->coords - oldcoords;
3313 Normalise(&relative);
3314 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3315 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3317 victim->jointVel(abdomen) += relative * damagemult * 200;
3318 victim->Puff(abdomen);
3319 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3321 award_bonus(id, Reversal);
3324 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3325 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3326 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3327 takeWeapon(victim->weaponids[victim->weaponactive]);
3328 victim->num_weapons--;
3329 if (victim->num_weapons > 0) {
3330 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3332 victim->weaponactive = -1;
3337 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3345 emit_sound_at(whooshhitsound, victim->coords, 128.);
3348 relative = victim->coords - oldcoords;
3350 Normalise(&relative);
3351 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3352 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3354 victim->jointVel(abdomen) += relative * damagemult * 200;
3356 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3359 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3368 award_bonus(id, staffreversebonus);
3370 if (tutoriallevel != 1) {
3371 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3374 award_bonus(id, staffreversebonus); // Huh, again?
3377 relative = victim->coords - oldcoords;
3379 Normalise(&relative);
3380 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3381 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3383 victim->jointVel(abdomen) += relative * damagemult * 200;
3385 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3388 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3394 Normalise(&relative);
3396 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3397 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3399 victim->jointVel(lefthand) *= .1;
3400 victim->jointVel(leftwrist) *= .2;
3401 victim->jointVel(leftelbow) *= .5;
3402 victim->jointVel(leftshoulder) *= .7;
3403 victim->jointVel(righthand) *= .1;
3404 victim->jointVel(rightwrist) *= .2;
3405 victim->jointVel(rightelbow) *= .5;
3406 victim->jointVel(rightshoulder) *= .7;
3408 victim->Puff(abdomen);
3409 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3411 award_bonus(id, Reversal);
3415 if (weaponactive != -1 || creature == wolftype)
3417 if (creature == rabbittype && weaponactive != -1)
3418 if (weapons[weaponids[0]].getType() == staff)
3421 if (weaponactive != -1) {
3422 victim->DoBloodBig(2 / victim->armorhigh, 225);
3423 emit_sound_at(knifeslicesound, victim->coords);
3424 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3425 weapons[weaponids[weaponactive]].bloody = 1;
3426 weapons[weaponids[weaponactive]].blooddrip += 3;
3428 if (weaponactive == -1 && creature == wolftype) {
3429 emit_sound_at(clawslicesound, victim->coords, 128.);
3431 victim->DoBloodBig(2 / victim->armorhigh, 175);
3438 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3444 Normalise(&relative);
3446 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3447 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3449 victim->jointVel(lefthand) *= .1 - 1;
3450 victim->jointVel(leftwrist) *= .2 - 1;
3451 victim->jointVel(leftelbow) *= .5 - 1;
3452 victim->jointVel(leftshoulder) *= .7 - 1;
3453 victim->jointVel(righthand) *= .1 - 1;
3454 victim->jointVel(rightwrist) *= .2 - 1;
3455 victim->jointVel(rightelbow) *= .5 - 1;
3456 victim->jointVel(rightshoulder) *= .7 - 1;
3458 award_bonus(id, swordreversebonus);
3461 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3469 if (tutoriallevel != 1) {
3470 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3474 relative = victim->coords - oldcoords;
3476 Normalise(&relative);
3477 relative = DoRotation(relative, 0, -90, 0);
3478 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3479 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3481 victim->jointVel(abdomen) += relative * damagemult * 200;
3482 victim->Puff(abdomen);
3483 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3485 award_bonus(id, Reversal);
3488 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3491 victim->skeleton.spinny = 0;
3493 relative = facing * -1;
3495 Normalise(&relative);
3496 if (victim->id == 0)
3498 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3499 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3501 victim->damage = victim->damagetolerance;
3502 victim->permanentdamage = victim->damagetolerance - 1;
3505 if (weaponactive != -1 || creature == wolftype)
3507 if (creature == rabbittype && weaponactive != -1)
3508 if (weapons[weaponids[0]].getType() == staff)
3511 if (weaponactive != -1) {
3512 victim->DoBloodBig(200, 225);
3513 emit_sound_at(knifeslicesound, victim->coords);
3515 weapons[weaponids[weaponactive]].bloody = 2;
3516 weapons[weaponids[weaponactive]].blooddrip += 5;
3519 if (creature == wolftype && weaponactive == -1) {
3520 emit_sound_at(clawslicesound, victim->coords, 128.);
3522 victim->DoBloodBig(2, 175);
3525 award_bonus(id, spinecrusher);
3528 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3529 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3531 if (animTarget == knifefollowanim)
3532 victim->DoBloodBig(200, 210);
3533 if (animTarget == knifesneakattackanim) {
3534 XYZ footvel, footpoint;
3536 footpoint = weapons[weaponids[0]].tippoint;
3538 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3539 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3540 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3541 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3542 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3543 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3544 victim->DoBloodBig(200, 195);
3545 award_bonus(id, tracheotomy);
3547 if (animTarget == knifefollowanim) {
3548 award_bonus(id, Stabbonus);
3549 XYZ footvel, footpoint;
3551 footpoint = weapons[weaponids[0]].tippoint;
3553 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3554 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3555 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3556 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3557 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3558 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3561 victim->bloodloss += 10000;
3562 victim->velocity = 0;
3563 emit_sound_at(fleshstabsound, victim->coords);
3565 weapons[weaponids[weaponactive]].bloody = 2;
3566 weapons[weaponids[weaponactive]].blooddrip += 5;
3570 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3572 victim->velocity = 0;
3573 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3574 victim->skeleton.joints[i].velocity = 0;
3576 if (animTarget == knifefollowanim) {
3578 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3579 victim->skeleton.joints[i].velocity = 0;
3582 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3583 emit_sound_at(fleshstabremovesound, victim->coords);
3585 weapons[weaponids[weaponactive]].bloody = 2;
3586 weapons[weaponids[weaponactive]].blooddrip += 5;
3588 XYZ footvel, footpoint;
3590 footpoint = weapons[weaponids[0]].tippoint;
3592 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3593 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3594 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3595 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3596 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3597 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3601 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3602 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3603 award_bonus(id, backstab);
3607 XYZ footvel, footpoint;
3609 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3611 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3612 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3613 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3614 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3615 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3616 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3617 victim->DoBloodBig(200, 180);
3618 victim->DoBloodBig(200, 215);
3619 victim->bloodloss += 10000;
3620 victim->velocity = 0;
3621 emit_sound_at(fleshstabsound, victim->coords);
3623 weapons[weaponids[weaponactive]].bloody = 2;
3624 weapons[weaponids[weaponactive]].blooddrip += 5;
3628 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3630 victim->velocity = 0;
3631 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3632 victim->skeleton.joints[i].velocity = 0;
3634 if (weaponactive != -1) {
3635 emit_sound_at(fleshstabremovesound, victim->coords);
3637 weapons[weaponids[weaponactive]].bloody = 2;
3638 weapons[weaponids[weaponactive]].blooddrip += 5;
3640 XYZ footvel, footpoint;
3642 footpoint = weapons[weaponids[0]].tippoint;
3644 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3645 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3646 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3647 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3648 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3649 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3653 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3661 if (weaponactive == -1) {
3662 if (tutoriallevel != 1) {
3663 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3668 if (weaponactive != -1 || creature == wolftype)
3670 if (creature == rabbittype && weaponactive != -1)
3671 if (weapons[weaponids[0]].getType() == staff)
3674 if (weaponactive != -1) {
3675 victim->DoBloodBig(2 / victim->armorhead, 225);
3676 emit_sound_at(knifeslicesound, victim->coords);
3677 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3678 weapons[weaponids[weaponactive]].bloody = 1;
3679 weapons[weaponids[weaponactive]].blooddrip += 3;
3681 if (weaponactive == -1 && creature == wolftype) {
3682 emit_sound_at(clawslicesound, victim->coords, 128.);
3684 victim->DoBloodBig(2 / victim->armorhead, 175);
3688 award_bonus(id, Reversal);
3693 relative = facing * -1;
3695 Normalise(&relative);
3696 relative = DoRotation(relative, 0, 90, 0);
3698 Normalise(&relative);
3699 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3700 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3702 victim->jointVel(head) += relative * damagemult * 200;
3703 if (victim->damage < victim->damagetolerance - 100)
3704 victim->velocity = relative * 200;
3705 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3706 victim->velocity = 0;
3709 if (animTarget == sweepreversalanim && ((Animation::animations[animTarget].frames[frameCurrent].label == 9 && victim->damage < victim->damagetolerance) || (Animation::animations[animTarget].frames[frameCurrent].label == 7 && victim->damage > victim->damagetolerance))) {
3713 relative = facing * -1;
3715 Normalise(&relative);
3716 relative = DoRotation(relative, 0, 90, 0);
3718 Normalise(&relative);
3719 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3720 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3722 victim->jointVel(head) += relative * damagemult * 200;
3725 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3726 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3727 award_bonus(id, reverseko);
3733 if (frameTarget > Animation::animations[animCurrent].frames.size() - 1) {
3736 animTarget = getIdle();
3737 FootLand(leftfoot, 1);
3738 FootLand(rightfoot, 1);
3740 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3741 animTarget = rollanim;
3743 emit_sound_at(movewhooshsound, coords, 128.);
3745 if (animCurrent == staggerbackhighanim) {
3746 animTarget = getIdle();
3748 if (animCurrent == staggerbackhardanim) {
3749 animTarget = getIdle();
3751 if (animCurrent == removeknifeanim) {
3752 animTarget = getIdle();
3754 if (animCurrent == crouchremoveknifeanim) {
3755 animTarget = getCrouch();
3757 if (animCurrent == backhandspringanim) {
3758 animTarget = getIdle();
3760 if (animCurrent == dodgebackanim) {
3761 animTarget = getIdle();
3763 if (animCurrent == drawleftanim) {
3764 animTarget = getIdle();
3766 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3767 animTarget = getIdle();
3768 if (animCurrent == crouchdrawrightanim) {
3769 animTarget = getCrouch();
3771 if (weaponactive == -1)
3773 else if (weaponactive == 0) {
3775 if (num_weapons == 2) {
3777 buffer = weaponids[0];
3778 weaponids[0] = weaponids[1];
3779 weaponids[1] = buffer;
3783 if (weaponactive == -1) {
3784 emit_sound_at(knifesheathesound, coords, 128.);
3786 if (weaponactive != -1) {
3787 emit_sound_at(knifedrawsound, coords, 128.);
3790 if (animCurrent == rollanim) {
3791 animTarget = getCrouch();
3792 FootLand(leftfoot, 1);
3793 FootLand(rightfoot, 1);
3796 if (animTarget == walljumprightkickanim) {
3799 if (animTarget == walljumpleftkickanim) {
3802 animTarget = jumpdownanim;
3804 if (animCurrent == climbanim) {
3805 animTarget = getCrouch();
3807 coords += facing * .1;
3808 if (!isnormal(coords.x))
3819 if (animTarget == rabbitkickreversalanim) {
3820 animTarget = getCrouch();
3823 if (animTarget == jumpreversalanim) {
3824 animTarget = getCrouch();
3827 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3828 if (attackkeydown && animTarget != walljumpfrontanim) {
3830 float closestdist = -1;
3832 if (Person::players.size() > 1)
3833 for (unsigned i = 0; i < Person::players.size(); i++) {
3834 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3835 distance = distsq(&Person::players[i]->coords, &coords);
3836 if (closestdist == -1 || distance < closestdist) {
3837 closestdist = distance;
3842 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3843 victim = Person::players[closest];
3844 animTarget = walljumprightkickanim;
3846 XYZ rotatetarget = victim->coords - coords;
3847 Normalise(&rotatetarget);
3848 yaw = -asin(0 - rotatetarget.x);
3850 if (rotatetarget.z < 0)
3852 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3853 velocity = (victim->coords - coords) * 4;
3858 if (animTarget == walljumpbackanim) {
3859 animTarget = backflipanim;
3861 velocity = facing * -8;
3864 resume_stream(whooshsound);
3866 if (animTarget == walljumprightanim) {
3867 animTarget = rightflipanim;
3871 velocity = DoRotation(facing, 0, 30, 0) * -8;
3874 if (animTarget == walljumpfrontanim) {
3875 animTarget = frontflipanim;
3879 velocity = facing * 8;
3883 resume_stream(whooshsound);
3885 if (animTarget == walljumpleftanim) {
3886 if (attackkeydown) {
3888 float closestdist = -1;
3890 if (Person::players.size() > 1)
3891 for (unsigned i = 0; i < Person::players.size(); i++) {
3892 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3893 distance = distsq(&Person::players[i]->coords, &coords);
3894 if (closestdist == -1 || distance < closestdist) {
3895 closestdist = distance;
3900 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3901 victim = Person::players[closest];
3902 animTarget = walljumpleftkickanim;
3904 XYZ rotatetarget = victim->coords - coords;
3905 Normalise(&rotatetarget);
3906 yaw = -asin(0 - rotatetarget.x);
3908 if (rotatetarget.z < 0)
3910 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3911 velocity = (victim->coords - coords) * 4;
3916 if (animTarget != walljumpleftkickanim) {
3917 animTarget = leftflipanim;
3921 velocity = DoRotation(facing, 0, -30, 0) * -8;
3925 resume_stream(whooshsound);
3927 if (animTarget == sneakattackanim) {
3928 animCurrent = getCrouch();
3929 animTarget = getCrouch();
3936 transspeed = 1000000;
3937 targetheadyaw += 180;
3938 coords -= facing * .7;
3940 coords.y = terrain.getHeight(coords.x, coords.z);
3944 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3945 animTarget = getIdle();
3948 coords.y = terrain.getHeight(coords.x, coords.z);
3952 if (animCurrent == knifefollowanim) {
3953 animTarget = getIdle();
3956 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3957 float ycoords = oldcoords.y;
3958 animTarget = getStop();
3963 transspeed = 1000000;
3964 targetheadyaw += 180;
3965 if (!isnormal(coords.x))
3967 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3968 oldcoords = coords + facing * .5;
3969 else if (animCurrent == sweepreversalanim)
3970 oldcoords = coords + facing * 1.1;
3971 else if (animCurrent == upunchreversalanim) {
3972 oldcoords = coords + facing * 1.5;
3975 targetheadyaw += 180;
3978 } else if (animCurrent == knifeslashreversalanim) {
3979 oldcoords = coords + facing * .5;
3982 targetheadyaw += 90;
3985 } else if (animCurrent == staffspinhitreversalanim) {
3988 targetheadyaw += 180;
3993 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3995 oldcoords.y = ycoords;
3996 currentoffset = coords - oldcoords;
4002 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4007 if (Animation::animations[animTarget].attack == reversed) {
4009 if (animTarget == sweepreversedanim)
4011 animTarget = backhandspringanim;
4013 emit_sound_at(landsound, coords, 128);
4015 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4016 animTarget = rollanim;
4019 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4020 coords.y = oldcoords.y;
4022 if (animCurrent == knifeslashreversedanim) {
4023 animTarget = rollanim;
4028 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4029 coords.y = oldcoords.y;
4033 animTarget = jumpdownanim;
4036 animTarget = getIdle();
4038 animTarget = getIdle();
4039 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4040 animTarget = getIdle();
4042 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4043 coords.y = oldcoords.y;
4044 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4045 targetoffset.y = coords.y;
4047 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4048 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4049 currentoffset.y -= (coords.y - targetoffset.y);
4050 coords.y = targetoffset.y;
4052 normalsupdatedelay = 0;
4054 if (animCurrent == upunchanim) {
4055 animTarget = getStop();
4056 normalsupdatedelay = 0;
4059 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4063 if (num_weapons > 0)
4064 if (weapons[0].getType() == staff)
4070 rabbitkickragdoll = 1;
4072 if (animCurrent == rabbitkickreversedanim) {
4078 skeleton.spinny = 0;
4079 SolidHitBonus(!id); // FIXME: tricky id
4083 animTarget = rollanim;
4086 pause_sound(whooshsound);
4090 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4094 skeleton.spinny = 0;
4096 if (animCurrent == jumpreversedanim) {
4102 skeleton.spinny = 0;
4103 SolidHitBonus(!id); // FIXME: tricky id
4107 animTarget = rollanim;
4108 coords += facing * 2;
4110 pause_sound(whooshsound);
4115 if (Animation::animations[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
4116 animTarget = getupfromfrontanim;
4118 } else if (Animation::animations[animCurrent].attack == normalattack) {
4119 animTarget = getIdle();
4122 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4123 animTarget = blockhighleftstrikeanim;
4125 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4126 animTarget = getIdle();
4129 if (animCurrent == spinkickanim && victim->skeleton.free) {
4130 if (creature == rabbittype)
4131 animTarget = fightidleanim;
4136 if (isIdle() && !wasIdle())
4137 normalsupdatedelay = 0;
4139 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4140 animTarget = jumpdownanim;
4143 if (!skeleton.free) {
4145 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4146 if (!isRun() || !wasRun()) {
4147 if (targetFrame().speed > currentFrame().speed)
4148 target += multiplier * targetFrame().speed * speed * 2;
4149 if (targetFrame().speed <= currentFrame().speed)
4150 target += multiplier * currentFrame().speed * speed * 2;
4152 if (isRun() && wasRun()) {
4154 tempspeed = velspeed;
4155 if (tempspeed < 10 * speedmult)
4156 tempspeed = 10 * speedmult;
4157 /* FIXME - mixed of target and current here, is that intended? */
4158 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4160 } else if (transspeed)
4161 target += multiplier * transspeed * speed * 2;
4163 if (!isRun() || !wasRun()) {
4164 if (targetFrame().speed > currentFrame().speed)
4165 target += multiplier * targetFrame().speed * 2;
4166 if (targetFrame().speed <= currentFrame().speed)
4167 target += multiplier * currentFrame().speed * 2;
4171 if (animCurrent != animTarget)
4172 target = (target + oldtarget) / 2;
4175 frameCurrent = frameTarget;
4179 rot = targetrot * target;
4180 yaw += rot - oldrot;
4186 if (frameCurrent >= Animation::animations[animCurrent].frames.size()) {
4187 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4189 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4191 for (int i = 0; i < skeleton.joints.size(); i++) {
4192 skeleton.joints[i].position = currentFrame().joints[i].position;
4195 skeleton.FindForwards();
4197 for (int i = 0; i < skeleton.muscles.size(); i++) {
4198 if (skeleton.muscles[i].visible) {
4199 skeleton.FindRotationMuscle(i, animTarget);
4202 for (int i = 0; i < skeleton.muscles.size(); i++) {
4203 if (skeleton.muscles[i].visible) {
4204 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4205 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4206 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4207 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4208 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4209 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4214 for (int i = 0; i < skeleton.joints.size(); i++) {
4215 skeleton.joints[i].position = targetFrame().joints[i].position;
4218 skeleton.FindForwards();
4220 for (int i = 0; i < skeleton.muscles.size(); i++) {
4221 if (skeleton.muscles[i].visible) {
4222 skeleton.FindRotationMuscle(i, animTarget);
4225 for (int i = 0; i < skeleton.muscles.size(); i++) {
4226 if (skeleton.muscles[i].visible) {
4227 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4228 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4229 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4230 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4231 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4232 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4233 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4234 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4235 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4236 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4237 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4238 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4243 oldanimCurrent = animCurrent;
4244 oldanimTarget = animTarget;
4245 oldframeTarget = frameTarget;
4246 oldframeCurrent = frameCurrent;
4248 for (int i = 0; i < skeleton.joints.size(); i++) {
4249 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4250 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4252 offset = currentoffset * (1 - target) + targetoffset * target;
4253 for (int i = 0; i < skeleton.muscles.size(); i++) {
4254 if (skeleton.muscles[i].visible) {
4255 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4256 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4257 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4262 if (isLanding() && landhard) {
4265 animTarget = getLandhard();
4278 void Person::DoStuff()
4280 static XYZ terrainnormal;
4281 static XYZ flatfacing;
4282 static XYZ flatvelocity;
4283 static float flatvelspeed;
4287 static int bloodsize;
4288 static int startx, starty, endx, endy;
4289 static GLubyte color;
4290 static XYZ bloodvel;
4292 onfiredelay -= multiplier;
4293 if (onfiredelay < 0 && onfire) {
4294 if (Random() % 2 == 0) {
4300 crouchkeydowntime += multiplier;
4302 crouchkeydowntime = 0;
4303 jumpkeydowntime += multiplier;
4304 if (!jumpkeydown && skeleton.free)
4305 jumpkeydowntime = 0;
4307 if (hostile || damage > 0 || bloodloss > 0)
4310 if (isIdle() || isRun())
4313 if (num_weapons == 1 && weaponactive != -1)
4317 blooddimamount -= multiplier * .3;
4318 speechdelay -= multiplier;
4319 texupdatedelay -= multiplier;
4320 interestdelay -= multiplier;
4321 flamedelay -= multiplier;
4322 parriedrecently -= multiplier;
4324 victim = this->shared_from_this();
4329 speed = 1.1 * speedmult;
4331 speed = 1.0 * speedmult;
4333 rabbitkickragdoll = 0;
4337 if (id != 0 && (creature == rabbittype || difficulty != 2))
4339 if (id != 0 && creature == wolftype && difficulty == 2) {
4341 if (aitype != passivetype) {
4343 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) {
4349 if (animTarget == wolfrunninganim && !superruntoggle) {
4350 animTarget = getRun();
4354 if (weaponactive == -1 && num_weapons > 0) {
4355 if (weapons[weaponids[0]].getType() == staff) {
4361 burnt += multiplier;
4365 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4367 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4373 vel[0] = velocity.x;
4374 vel[1] = velocity.y;
4375 vel[2] = velocity.z;
4378 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4379 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4383 while (flamedelay < 0 && onfire) {
4385 howmany = abs(Random() % (skeleton.joints.size()));
4386 if (skeleton.free) {
4387 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4388 flatfacing = skeleton.joints[howmany].position * scale + coords;
4390 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4391 flatvelocity = (coords - oldcoords) / multiplier / 2;
4393 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4396 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4398 howmany = abs(Random() % (skeleton.joints.size()));
4399 if (skeleton.free) {
4400 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4401 flatfacing = skeleton.joints[howmany].position * scale + coords;
4403 flatvelocity = (coords - oldcoords) / multiplier / 2;
4404 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4406 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4410 bleeding -= multiplier * .3;
4411 if (bloodtoggle == 2) {
4412 skeleton.drawmodel.textureptr.bind();
4413 if ((bleeding <= 0) && (detail != 2))
4418 if (neckspurtamount > 0) {
4419 neckspurtamount -= multiplier;
4420 neckspurtdelay -= multiplier * 3;
4421 neckspurtparticledelay -= multiplier * 3;
4422 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4425 if (skeleton.free) {
4426 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4427 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4428 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4430 bloodvel.z = 5 * neckspurtamount;
4431 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4432 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4433 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4435 neckspurtparticledelay = .05;
4437 if (neckspurtdelay < 0) {
4442 if (deathbleeding > 0 && dead != 2) {
4443 if (deathbleeding < 5)
4444 bleeddelay -= deathbleeding * multiplier / 4;
4446 bleeddelay -= 5 * multiplier / 4;
4447 if (bleeddelay < 0 && bloodtoggle) {
4452 if (skeleton.free) {
4453 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4454 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4456 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4457 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4461 bloodloss += deathbleeding * multiplier * 80;
4462 deathbleeding -= multiplier * 1.6;
4463 if (deathbleeding < 0)
4465 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4466 if (weaponactive != -1) {
4467 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4468 weapons[weaponids[0]].velocity.x += .01;
4471 weaponids[0] = weaponids[num_weapons];
4472 if (weaponstuck == num_weapons)
4476 for (unsigned i = 0; i < Person::players.size(); i++) {
4477 Person::players[i]->wentforweapon = 0;
4485 if (!dead && creature == wolftype) {
4486 award_bonus(0, Wolfbonus);
4489 if (animTarget == knifefollowedanim && !skeleton.free) {
4490 for (int i = 0; i < skeleton.joints.size(); i++) {
4491 skeleton.joints[i].velocity = 0;
4492 skeleton.joints[i].velocity.y = -2;
4495 if (id != 0 && unconscioustime > .1) {
4503 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4504 texupdatedelay = .12;
4506 bloodsize = 5 - realtexdetail;
4510 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4511 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4512 endx = startx + bloodsize;
4513 endy = starty + bloodsize;
4523 if (endx > skeleton.skinsize - 1) {
4524 endx = skeleton.skinsize - 1;
4527 if (endy > skeleton.skinsize - 1) {
4528 endy = skeleton.skinsize - 1;
4536 for (i = startx; i < endx; i++) {
4537 for (j = starty; j < endy; j++) {
4538 if (Random() % 2 == 0) {
4539 color = Random() % 85 + 170;
4540 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4541 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4542 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4543 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4548 skeleton.drawmodel.textureptr.bind();
4552 if (skeleton.free) {
4553 bleedx += 4 * direction / realtexdetail;
4555 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4557 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4559 bleedy -= 4 / realtexdetail;
4561 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4563 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4567 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4568 righthandmorphness = targetrighthandmorphness;
4569 righthandmorphstart = righthandmorphend;
4570 } else if (righthandmorphness > targetrighthandmorphness) {
4571 righthandmorphness -= multiplier * 4;
4572 } else if (righthandmorphness < targetrighthandmorphness) {
4573 righthandmorphness += multiplier * 4;
4576 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4577 lefthandmorphness = targetlefthandmorphness;
4578 lefthandmorphstart = lefthandmorphend;
4579 } else if (lefthandmorphness > targetlefthandmorphness) {
4580 lefthandmorphness -= multiplier * 4;
4581 } else if (lefthandmorphness < targetlefthandmorphness) {
4582 lefthandmorphness += multiplier * 4;
4585 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4586 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4587 tailmorphness = targettailmorphness;
4588 tailmorphstart = tailmorphend;
4589 } else if (tailmorphness > targettailmorphness) {
4590 tailmorphness -= multiplier * 10;
4591 } else if (tailmorphness < targettailmorphness) {
4592 tailmorphness += multiplier * 10;
4596 if (creature == wolftype) {
4597 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4598 tailmorphness = targettailmorphness;
4599 tailmorphstart = tailmorphend;
4600 } else if (tailmorphness > targettailmorphness) {
4601 tailmorphness -= multiplier * 2;
4602 } else if (tailmorphness < targettailmorphness) {
4603 tailmorphness += multiplier * 2;
4607 if (headmorphend == 3 || headmorphstart == 3) {
4608 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4609 headmorphness = targetheadmorphness;
4610 headmorphstart = headmorphend;
4611 } else if (headmorphness > targetheadmorphness) {
4612 headmorphness -= multiplier * 7;
4613 } else if (headmorphness < targetheadmorphness) {
4614 headmorphness += multiplier * 7;
4616 } else if (headmorphend == 5 || headmorphstart == 5) {
4617 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4618 headmorphness = targetheadmorphness;
4619 headmorphstart = headmorphend;
4620 } else if (headmorphness > targetheadmorphness) {
4621 headmorphness -= multiplier * 10;
4622 } else if (headmorphness < targetheadmorphness) {
4623 headmorphness += multiplier * 10;
4626 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4627 headmorphness = targetheadmorphness;
4628 headmorphstart = headmorphend;
4629 } else if (headmorphness > targetheadmorphness) {
4630 headmorphness -= multiplier * 4;
4631 } else if (headmorphness < targetheadmorphness) {
4632 headmorphness += multiplier * 4;
4636 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4637 chestmorphness = targetchestmorphness;
4638 chestmorphstart = chestmorphend;
4639 } else if (chestmorphness > targetchestmorphness) {
4640 chestmorphness -= multiplier;
4641 } else if (chestmorphness < targetchestmorphness) {
4642 chestmorphness += multiplier;
4645 if (dead != 2 && howactive <= typesleeping) {
4646 if (chestmorphstart == 0 && chestmorphend == 0) {
4648 targetchestmorphness = 1;
4651 if (chestmorphstart != 0 && chestmorphend != 0) {
4653 targetchestmorphness = 1;
4655 if (environment == snowyenvironment) {
4658 if (skeleton.free) {
4659 footvel = skeleton.specialforward[0] * -1;
4660 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4662 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4663 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4665 if (animTarget == sleepanim)
4666 footvel = DoRotation(footvel, 0, 90, 0);
4667 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4671 if (!dead && howactive < typesleeping) {
4672 blinkdelay -= multiplier * 2;
4673 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4675 targetheadmorphness = 1;
4677 blinkdelay = (float)(abs(Random() % 40)) / 5;
4679 if (headmorphstart == 3 && headmorphend == 3) {
4681 targetheadmorphness = 1;
4686 twitchdelay -= multiplier * 1.5;
4687 if (animTarget != hurtidleanim) {
4688 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4690 targetheadmorphness = 1;
4692 twitchdelay = (float)(abs(Random() % 40)) / 5;
4694 if (headmorphstart == 5 && headmorphend == 5) {
4696 targetheadmorphness = 1;
4700 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4701 twitchdelay3 -= multiplier * 1;
4702 if (Random() % 2 == 0) {
4703 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4704 righthandmorphness = 0;
4705 targetrighthandmorphness = 1;
4706 righthandmorphend = 1;
4707 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4709 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4710 righthandmorphness = 0;
4711 targetrighthandmorphness = 1;
4712 righthandmorphend = 0;
4715 if (Random() % 2 == 0) {
4716 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4717 lefthandmorphness = 0;
4718 targetlefthandmorphness = 1;
4719 lefthandmorphend = 1;
4720 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4722 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4723 lefthandmorphness = 0;
4724 targetlefthandmorphness = 1;
4725 lefthandmorphend = 0;
4731 if (creature == rabbittype) {
4732 if (howactive < typesleeping)
4733 twitchdelay2 -= multiplier * 1.5;
4735 twitchdelay2 -= multiplier * 0.5;
4736 if (howactive <= typesleeping) {
4737 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4739 targettailmorphness = 1;
4741 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4743 if (tailmorphstart == 1 && tailmorphend == 1) {
4745 targettailmorphness = 1;
4748 if (tailmorphstart == 2 && tailmorphend == 2) {
4750 targettailmorphness = 1;
4757 if (creature == wolftype) {
4758 twitchdelay2 -= multiplier * 1.5;
4759 if (tailmorphend != 0)
4760 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4762 targettailmorphness = 1;
4766 if (tailmorphend != 5)
4767 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4769 targettailmorphness = 1;
4773 if (twitchdelay2 <= 0) {
4774 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4776 targettailmorphness = 1;
4779 if (tailmorphstart == 1 && tailmorphend == 1) {
4781 targettailmorphness = 1;
4784 if (tailmorphstart == 2 && tailmorphend == 2) {
4786 targettailmorphness = 1;
4789 if (tailmorphstart == 3 && tailmorphend == 3) {
4791 targettailmorphness = 1;
4794 if (tailmorphstart == 4 && tailmorphend == 4) {
4796 targettailmorphness = 1;
4803 unconscioustime = 0;
4805 if (dead == 1 || howactive == typesleeping) {
4806 unconscioustime += multiplier;
4807 //If unconscious, close eyes and mouth
4808 if (righthandmorphend != 0)
4809 righthandmorphness = 0;
4810 righthandmorphend = 0;
4811 targetrighthandmorphness = 1;
4813 if (lefthandmorphend != 0)
4814 lefthandmorphness = 0;
4815 lefthandmorphend = 0;
4816 targetlefthandmorphness = 1;
4818 if (headmorphend != 3 && headmorphend != 5)
4821 targetheadmorphness = 1;
4825 if (howactive > typesleeping) {
4828 if (bloodtoggle && !bled) {
4829 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4831 if (bloodtoggle && !bled)
4832 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4833 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4834 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4838 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4843 if (dead == 2 || howactive > typesleeping) {
4844 //If dead, open mouth and hands
4845 if (righthandmorphend != 0)
4846 righthandmorphness = 0;
4847 righthandmorphend = 0;
4848 targetrighthandmorphness = 1;
4850 if (lefthandmorphend != 0)
4851 lefthandmorphness = 0;
4852 lefthandmorphend = 0;
4853 targetlefthandmorphness = 1;
4855 if (headmorphend != 2)
4858 targetheadmorphness = 1;
4861 if (stunned > 0 && !dead && headmorphend != 2) {
4862 if (headmorphend != 4)
4865 targetheadmorphness = 1;
4868 if (damage > damagetolerance && !dead) {
4871 unconscioustime = 0;
4873 if (creature == wolftype) {
4874 award_bonus(0, Wolfbonus);
4879 if (weaponactive != -1) {
4880 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4881 weapons[weaponids[0]].velocity.x += .01;
4884 weaponids[0] = weaponids[num_weapons];
4885 if (weaponstuck == num_weapons)
4889 for (unsigned i = 0; i < Person::players.size(); i++) {
4890 Person::players[i]->wentforweapon = 0;
4896 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4905 damage -= multiplier * 13;
4907 permanentdamage -= multiplier * 4;
4908 if (isIdle() || isCrouch()) {
4910 permanentdamage -= multiplier * 4;
4914 if (permanentdamage < 0)
4915 permanentdamage = 0;
4916 if (superpermanentdamage < 0)
4917 superpermanentdamage = 0;
4918 if (permanentdamage < superpermanentdamage) {
4919 permanentdamage = superpermanentdamage;
4921 if (damage < permanentdamage) {
4922 damage = permanentdamage;
4924 if (dead == 1 && damage < damagetolerance) {
4928 for (int i = 0; i < skeleton.joints.size(); i++) {
4929 skeleton.joints[i].velocity = 0;
4932 if (permanentdamage > damagetolerance && dead != 2) {
4935 if (weaponactive != -1) {
4936 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4937 weapons[weaponids[0]].velocity.x += .01;
4940 weaponids[0] = weaponids[num_weapons];
4941 if (weaponstuck == num_weapons)
4945 for (unsigned i = 0; i < Person::players.size(); i++) {
4946 Person::players[i]->wentforweapon = 0;
4952 if (!dead && creature == wolftype) {
4953 award_bonus(0, Wolfbonus);
4956 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4957 award_bonus(id, touchofdeath);
4958 if (id != 0 && unconscioustime > .1) {
4966 emit_sound_at(breaksound, coords);
4969 if (skeleton.free == 1) {
4971 pause_sound(whooshsound);
4974 //If knocked over, open hands and close mouth
4975 if (righthandmorphend != 0)
4976 righthandmorphness = 0;
4977 righthandmorphend = 0;
4978 targetrighthandmorphness = 1;
4980 if (lefthandmorphend != 0)
4981 lefthandmorphness = 0;
4982 lefthandmorphend = 0;
4983 targetlefthandmorphness = 1;
4985 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4986 if (headmorphend != 0)
4989 targetheadmorphness = 1;
4993 skeleton.DoGravity(&scale);
4995 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4996 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4997 award_bonus(id, deepimpact);
4998 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5002 for (j = 0; j < skeleton.joints.size(); j++) {
5003 average += skeleton.joints[j].position;
5007 coords += average * scale;
5008 for (j = 0; j < skeleton.joints.size(); j++) {
5009 skeleton.joints[j].position -= average;
5011 average /= multiplier;
5014 for (int i = 0; i < skeleton.joints.size(); i++) {
5015 velocity += skeleton.joints[i].velocity * scale;
5017 velocity /= skeleton.joints.size();
5019 if (!isnormal(velocity.x) && velocity.x) {
5023 if (findLength(&average) < 10 && dead && skeleton.free) {
5024 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5025 if (skeleton.longdead > 2000) {
5026 if (skeleton.longdead > 6000) {
5028 pause_sound(whooshsound);
5033 if (dead == 2 && bloodloss < damagetolerance) {
5035 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5037 if (bloodtoggle && !bled) {
5038 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5040 if (bloodtoggle && !bled)
5041 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5042 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5043 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5044 float size = .2 * 1.2;
5047 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5051 if (dead == 2 && bloodloss >= damagetolerance) {
5053 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5056 if (bloodtoggle && !bled) {
5057 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5059 if (bloodtoggle && !bled)
5060 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5061 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5062 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5066 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5073 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5074 bool canrecover = 1;
5075 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5076 startpoint = coords;
5079 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5081 if (velocity.y < -30)
5083 for (i = 0; i < objects.numobjects; i++) {
5084 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5085 colviewer = startpoint;
5086 coltarget = endpoint;
5087 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5096 terrainnormal = jointPos(groin) - jointPos(abdomen);
5097 if (joint(groin).locked && joint(abdomen).locked) {
5098 terrainnormal = jointPos(groin) - jointPos(abdomen);
5099 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5101 if (joint(abdomen).locked && joint(neck).locked) {
5102 terrainnormal = jointPos(abdomen) - jointPos(neck);
5103 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5105 if (joint(groin).locked && joint(neck).locked) {
5106 terrainnormal = jointPos(groin) - jointPos(neck);
5107 middle = (jointPos(groin) + jointPos(neck)) / 2;
5109 Normalise(&terrainnormal);
5111 targetyaw = -asin(0 - terrainnormal.x);
5112 targetyaw *= 360 / 6.28;
5113 if (terrainnormal.z < 0)
5114 targetyaw = 180 - targetyaw;
5118 animTarget = flipanim;
5119 crouchtogglekeydown = 1;
5124 animCurrent = tempanim;
5128 for (int i = 0; i < skeleton.joints.size(); i++) {
5129 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5130 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5135 if (findLength(&average) < 10 && !dead && skeleton.free) {
5136 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5137 if (skeleton.longdead > (damage + 500) * 1.5) {
5139 pause_sound(whooshsound);
5145 terrainnormal = jointPos(groin) - jointPos(abdomen);
5146 if (joint(groin).locked && joint(abdomen).locked) {
5147 terrainnormal = jointPos(groin) - jointPos(abdomen);
5148 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5150 if (joint(abdomen).locked && joint(neck).locked) {
5151 terrainnormal = jointPos(abdomen) - jointPos(neck);
5152 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5154 if (joint(groin).locked && joint(neck).locked) {
5155 terrainnormal = jointPos(groin) - jointPos(neck);
5156 middle = (jointPos(groin) + jointPos(neck)) / 2;
5158 Normalise(&terrainnormal);
5160 targetyaw = -asin(0 - terrainnormal.x);
5161 targetyaw *= 360 / 6.28;
5162 if (terrainnormal.z < 0)
5163 targetyaw = 180 - targetyaw;
5166 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5169 if (skeleton.forward.y < 0) {
5170 animTarget = getupfrombackanim;
5174 if (skeleton.forward.y > -.3) {
5175 animTarget = getupfromfrontanim;
5183 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5184 animTarget = rollanim;
5185 targetyaw = lookyaw;
5202 if ( !leftkeydown && !rightkeydown)
5209 if (abs(targettilt2) > 50)
5211 animCurrent = tempanim;
5214 tilt2 = targettilt2;
5216 if (middle.y > 0 && animTarget != rollanim)
5217 targetoffset.y = middle.y + 1;
5219 for (int i = 0; i < skeleton.joints.size(); i++) {
5220 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5221 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5228 if (num_weapons > 0)
5229 if (weapons[0].getType() == staff)
5231 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5232 if (velocity.y > -30) {
5234 tempvelocity = velocity;
5235 Normalise(&tempvelocity);
5236 targetyaw = -asin(0 - tempvelocity.x);
5237 targetyaw *= 360 / 6.28;
5239 targetyaw = 180 - targetyaw;
5243 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5244 animTarget = rollanim;
5247 animTarget = backhandspringanim;
5253 emit_sound_at(movewhooshsound, coords, 128.);
5255 animCurrent = animTarget;
5256 frameCurrent = frameTarget - 1;
5268 if (skeleton.freefall == 0)
5273 if (aitype != passivetype || skeleton.free == 1)
5274 if (findLengthfast(&velocity) > .1)
5275 for (i = 0; i < objects.numobjects; i++) {
5276 if (objects.type[i] == firetype)
5277 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) {
5279 if (!objects.onfire[i]) {
5280 emit_sound_at(firestartsound, objects.position[i]);
5282 objects.onfire[i] = 1;
5285 if (objects.onfire[i]) {
5290 if (objects.type[i] == bushtype)
5291 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) {
5293 if (!objects.onfire[i]) {
5294 emit_sound_at(firestartsound, objects.position[i]);
5296 objects.onfire[i] = 1;
5300 if (objects.onfire[i]) {
5304 if (objects.messedwith[i] <= 0) {
5308 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5311 addEnvSound(coords, 4 * findLength(&velocity));
5315 if (environment == grassyenvironment)
5316 howmany = findLength(&velocity) * 4;
5317 if (environment == snowyenvironment)
5318 howmany = findLength(&velocity) * 2;
5320 if (environment != desertenvironment)
5321 for (j = 0; j < howmany; j++) {
5322 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5323 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5324 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5327 pos.x += float(abs(Random() % 100) - 50) / 200;
5328 pos.y += float(abs(Random() % 100) - 50) / 200;
5329 pos.z += float(abs(Random() % 100) - 50) / 200;
5330 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);
5331 Sprite::setLastSpriteSpecial(1);
5333 howmany = findLength(&velocity) * 4;
5335 if (environment == snowyenvironment)
5336 for (j = 0; j < howmany; j++) {
5337 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5338 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5339 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5342 pos.x += float(abs(Random() % 100) - 50) / 200;
5343 pos.y += float(abs(Random() % 100) - 50) / 200;
5344 pos.z += float(abs(Random() % 100) - 50) / 200;
5345 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5346 Sprite::setLastSpriteSpecial(2);
5349 objects.rotx[i] += velocity.x * multiplier * 6;
5350 objects.roty[i] += velocity.z * multiplier * 6;
5351 objects.messedwith[i] = .5;
5354 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5355 if (objects.pitch[i] == 0)
5358 tempcoord = coords - objects.position[i];
5359 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5360 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5361 tempcoord += objects.position[i];
5363 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]) {
5364 if (objects.messedwith[i] <= 0) {
5368 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5371 addEnvSound(coords, 4 * findLength(&velocity));
5375 if (environment == grassyenvironment)
5376 howmany = findLength(&velocity) * 4;
5377 if (environment == snowyenvironment)
5378 howmany = findLength(&velocity) * 2;
5380 if (environment != desertenvironment)
5381 for (j = 0; j < howmany; j++) {
5382 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5383 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5384 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5386 pos += velocity * .1;
5388 pos.x += float(abs(Random() % 100) - 50) / 150;
5389 pos.y += float(abs(Random() % 100) - 50) / 150;
5390 pos.z += float(abs(Random() % 100) - 50) / 150;
5391 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);
5392 Sprite::setLastSpriteSpecial(1);
5394 howmany = findLength(&velocity) * 4;
5396 if (environment == snowyenvironment)
5397 for (j = 0; j < howmany; j++) {
5398 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5399 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5400 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5402 pos += velocity * .1;
5404 pos.x += float(abs(Random() % 100) - 50) / 150;
5405 pos.y += float(abs(Random() % 100) - 50) / 150;
5406 pos.z += float(abs(Random() % 100) - 50) / 150;
5407 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5408 Sprite::setLastSpriteSpecial(2);
5411 objects.messedwith[i] = .5;
5416 if (!skeleton.free) {
5419 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5422 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5424 if (tutoriallevel == 1 && id != 0)
5426 if (play && aitype != playercontrolled) {
5427 int whichsound = -1;
5428 i = abs(Random() % 4);
5429 if (speechdelay <= 0) {
5430 if (creature == rabbittype) {
5432 whichsound = rabbitchitter;
5434 whichsound = rabbitchitter2;
5436 if (creature == wolftype) {
5438 whichsound = growlsound;
5440 whichsound = growl2sound;
5445 if (whichsound != -1) {
5446 emit_sound_at(whichsound, coords);
5450 if (animTarget == staggerbackhighanim)
5452 if (animTarget == staggerbackhardanim)
5454 staggerdelay -= multiplier;
5455 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5457 if (velocity.y < -30 && animTarget == jumpdownanim)
5459 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5460 animTarget = getIdle();
5464 weaponmissdelay -= multiplier;
5465 highreversaldelay -= multiplier;
5466 lowreversaldelay -= multiplier;
5467 lastcollide -= multiplier;
5468 skiddelay -= multiplier;
5469 if (!isnormal(velocity.x) && velocity.x) {
5472 if (!isnormal(targettilt) && targettilt) {
5475 if (!isnormal(targettilt2) && targettilt2) {
5478 if (!isnormal(targetyaw) && targetyaw) {
5482 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5483 //open hands and close mouth
5484 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5485 righthandmorphness = 0;
5486 righthandmorphend = 0;
5487 targetrighthandmorphness = 1;
5490 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5491 lefthandmorphness = 0;
5492 lefthandmorphend = 0;
5493 targetlefthandmorphness = 1;
5496 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5499 targetheadmorphness = 1;
5503 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) {
5504 //open hands and mouth
5505 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5506 righthandmorphness = 0;
5507 righthandmorphend = 0;
5508 targetrighthandmorphness = 1;
5511 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5512 lefthandmorphness = 0;
5513 lefthandmorphend = 0;
5514 targetlefthandmorphness = 1;
5517 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5520 targetheadmorphness = 1;
5524 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5525 //close hands and mouth
5526 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5527 righthandmorphness = 0;
5528 righthandmorphend = 1;
5529 targetrighthandmorphness = 1;
5532 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5533 lefthandmorphness = 0;
5534 lefthandmorphend = 1;
5535 targetlefthandmorphness = 1;
5538 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5541 targetheadmorphness = 1;
5545 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) {
5546 //close hands and yell
5547 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5548 righthandmorphness = 0;
5549 righthandmorphend = 1;
5550 targetrighthandmorphness = 1;
5553 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5554 lefthandmorphness = 0;
5555 lefthandmorphend = 1;
5556 targetlefthandmorphness = 1;
5559 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5562 targetheadmorphness = 1;
5569 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5570 (victim->aitype != searchtype) && (aitype != passivetype) &&
5571 (aitype != searchtype) && (victim->id < Person::players.size())) {
5572 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5576 if (!dead && animTarget != hurtidleanim)
5577 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5578 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5581 targetheadmorphness = 1;
5585 if (weaponactive != -1) {
5586 if (weapons[weaponids[weaponactive]].getType() != staff) {
5587 righthandmorphstart = 1;
5588 righthandmorphend = 1;
5590 if (weapons[weaponids[weaponactive]].getType() == staff) {
5591 righthandmorphstart = 2;
5592 righthandmorphend = 2;
5594 targetrighthandmorphness = 1;
5597 terrainnormal = terrain.getNormal(coords.x, coords.z);
5599 if (Animation::animations[animTarget].attack != reversal) {
5600 if (!isnormal(coords.x))
5608 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5609 facing = flatfacing;
5610 ReflectVector(&facing, terrainnormal);
5613 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5615 targettilt2 = -facing.y * 20;
5620 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5622 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5623 flatvelocity = velocity;
5625 flatvelspeed = findLength(&flatvelocity);
5626 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5627 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5632 if (targettilt > 25)
5634 if (targettilt < -25)
5638 if (targettilt2 > 45)
5640 if (targettilt2 < -45)
5642 if (abs(tilt2 - targettilt2) < multiplier * 400)
5643 tilt2 = targettilt2;
5644 else if (tilt2 > targettilt2) {
5645 tilt2 -= multiplier * 400;
5646 } else if (tilt2 < targettilt2) {
5647 tilt2 += multiplier * 400;
5649 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5656 if (!isnormal(targettilt) && targettilt) {
5659 if (!isnormal(targettilt2) && targettilt2) {
5664 if (animTarget == rabbittackleanim) {
5665 velocity += facing * multiplier * speed * 700 * scale;
5666 velspeed = findLength(&velocity);
5667 if (velspeed > speed * 65 * scale) {
5668 velocity /= velspeed;
5669 velspeed = speed * 65 * scale;
5670 velocity *= velspeed;
5672 velocity.y += gravity * multiplier * 20;
5673 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5674 velspeed = findLength(&velocity);
5675 velocity = flatfacing * velspeed;
5677 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5678 if (isRun() || animTarget == rabbitkickanim) {
5679 velocity += facing * multiplier * speed * 700 * scale;
5680 velspeed = findLength(&velocity);
5681 if (velspeed > speed * 45 * scale) {
5682 velocity /= velspeed;
5683 velspeed = speed * 45 * scale;
5684 velocity *= velspeed;
5686 velocity.y += gravity * multiplier * 20;
5687 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5688 velspeed = findLength(&velocity);
5689 if (velspeed < speed * 30 * scale)
5690 velspeed = speed * 30 * scale;
5691 velocity = flatfacing * velspeed;
5693 } else if (isRun()) {
5694 velocity += facing * multiplier * speed * 700 * scale;
5695 velspeed = findLength(&velocity);
5696 if (creature == rabbittype) {
5697 if (velspeed > speed * 55 * scale) {
5698 velocity /= velspeed;
5699 velspeed = speed * 55 * scale;
5700 velocity *= velspeed;
5703 if (creature == wolftype) {
5704 if (velspeed > speed * 75 * scale) {
5705 velocity /= velspeed;
5706 velspeed = speed * 75 * scale;
5707 velocity *= velspeed;
5710 velocity.y += gravity * multiplier * 20;
5711 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5712 velspeed = findLength(&velocity);
5713 velocity = flatfacing * velspeed;
5716 if (animTarget == rollanim && targetFrame().label != 6) {
5717 velocity += facing * multiplier * speed * 700 * scale;
5718 velspeed = findLength(&velocity);
5719 if (velspeed > speed * 45 * scale) {
5720 velocity /= velspeed;
5721 velspeed = speed * 45 * scale;
5722 velocity *= velspeed;
5724 velocity.y += gravity * multiplier * 20;
5725 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5726 velspeed = findLength(&velocity);
5727 velocity = flatfacing * velspeed;
5730 if (animTarget == sneakanim || animTarget == walkanim) {
5731 velocity += facing * multiplier * speed * 700 * scale;
5732 velspeed = findLength(&velocity);
5733 if (velspeed > speed * 12 * scale) {
5734 velocity /= velspeed;
5735 velspeed = speed * 12 * scale;
5736 velocity *= velspeed;
5738 velocity.y += gravity * multiplier * 20;
5739 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5740 velspeed = findLength(&velocity);
5741 velocity = flatfacing * velspeed;
5744 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5745 velocity += facing * multiplier * speed * 700 * scale;
5746 velspeed = findLength(&velocity);
5747 if (velspeed > speed * 2 * scale) {
5748 velocity /= velspeed;
5749 velspeed = speed * 2 * scale;
5750 velocity *= velspeed;
5752 velocity.y += gravity * multiplier * 20;
5753 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5754 velspeed = findLength(&velocity);
5755 velocity = flatfacing * velspeed;
5759 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5760 velocity -= facing * multiplier * speed * 700 * scale;
5761 velspeed = findLength(&velocity);
5762 if (velspeed > speed * 2 * scale) {
5763 velocity /= velspeed;
5764 velspeed = speed * 2 * scale;
5765 velocity *= velspeed;
5767 velocity.y += gravity * multiplier * 20;
5768 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5769 velspeed = findLength(&velocity);
5770 velocity = flatfacing * velspeed * -1;
5773 if (animTarget == fightsidestep) {
5774 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5775 velspeed = findLength(&velocity);
5776 if (velspeed > speed * 12 * scale) {
5777 velocity /= velspeed;
5778 velspeed = speed * 12 * scale;
5779 velocity *= velspeed;
5781 velocity.y += gravity * multiplier * 20;
5782 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5783 velspeed = findLength(&velocity);
5784 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5787 if (animTarget == staggerbackhighanim) {
5788 coords -= facing * multiplier * speed * 16 * scale;
5791 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5792 coords -= facing * multiplier * speed * 20 * scale;
5796 if (animTarget == backhandspringanim) {
5797 //coords-=facing*multiplier*50*scale;
5798 velocity += facing * multiplier * speed * 700 * scale * -1;
5799 velspeed = findLength(&velocity);
5800 if (velspeed > speed * 50 * scale) {
5801 velocity /= velspeed;
5802 velspeed = speed * 50 * scale;
5803 velocity *= velspeed;
5805 velocity.y += gravity * multiplier * 20;
5806 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5807 velspeed = findLength(&velocity);
5808 velocity = flatfacing * velspeed * -1;
5810 if (animTarget == dodgebackanim) {
5811 //coords-=facing*multiplier*50*scale;
5812 velocity += facing * multiplier * speed * 700 * scale * -1;
5813 velspeed = findLength(&velocity);
5814 if (velspeed > speed * 60 * scale) {
5815 velocity /= velspeed;
5816 velspeed = speed * 60 * scale;
5817 velocity *= velspeed;
5819 velocity.y += gravity * multiplier * 20;
5820 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5821 velspeed = findLength(&velocity);
5822 velocity = flatfacing * velspeed * -1;
5825 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5826 velspeed = findLength(&velocity);
5830 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5831 velocity.y += gravity * multiplier;
5834 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5835 coords += velocity * multiplier;
5837 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5838 if (isFlip() && targetFrame().label == 7)
5841 if (animTarget == jumpupanim) {
5843 animTarget = getIdle();
5850 pause_sound(whooshsound);
5851 OPENAL_SetVolume(channels[whooshsound], 0);
5854 if (animTarget == jumpdownanim || isFlip()) {
5855 if (isFlip())jumppower = -4;
5856 animTarget = getLanding();
5857 emit_sound_at(landsound, coords, 128.);
5860 addEnvSound(coords);
5865 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5866 coords.y += gravity * multiplier * 2;
5867 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5868 coords.y = terrain.getHeight(coords.x, coords.z);
5873 if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || Animation::animations[animTarget].attack || (animTarget == rollanim && targetFrame().label == 6)) {
5874 velspeed = findLength(&velocity);
5876 if (velspeed < multiplier * 300 * scale) {
5879 velocity -= velocity / velspeed * multiplier * 300 * scale;
5880 if (velspeed > 5 && (isLanding() || isLandhard())) {
5881 skiddingdelay += multiplier;
5882 if (skiddelay <= 0) {
5883 FootLand(leftfoot, .5);
5884 FootLand(rightfoot, .5);
5892 velspeed = findLength(&velocity);
5894 if (velspeed < multiplier * 600 * scale) {
5897 velocity -= velocity / velspeed * multiplier * 600 * scale;
5899 if (velspeed > 5 && (isLanding() || isLandhard())) {
5900 skiddingdelay += multiplier;
5901 if (skiddelay <= 0) {
5902 FootLand(leftfoot, .5);
5903 FootLand(rightfoot, .5);
5910 if (skiddingdelay < 0)
5911 skiddingdelay += multiplier;
5912 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5914 if (!onterrain || environment == grassyenvironment) {
5915 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5917 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5921 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5922 terrainnormal = victim->coords - coords;
5923 Normalise(&terrainnormal);
5924 targetyaw = -asin(0 - terrainnormal.x);
5925 targetyaw *= 360 / 6.28;
5926 if (terrainnormal.z < 0)
5927 targetyaw = 180 - targetyaw;
5928 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5931 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5932 targetyaw = victim->targetyaw;
5934 if (animTarget == rabbittacklinganim) {
5935 coords = victim->coords;
5938 skeleton.oldfree = skeleton.free;
5942 midterrain.x = terrain.size * terrain.scale / 2;
5943 midterrain.z = terrain.size * terrain.scale / 2;
5944 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5946 tempposit = coords - midterrain;
5948 Normalise(&tempposit);
5949 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5950 coords.x = tempposit.x + midterrain.x;
5951 coords.z = tempposit.z + midterrain.z;
5957 * inverse kinematics helper function
5959 void IKHelper(Person *p, float interp)
5961 XYZ point, change, change2;
5962 float heightleft, heightright;
5964 // TODO: implement localToWorld and worldToLocal
5965 // but keep in mind it won't be the same math if player is ragdolled or something
5966 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5967 // then comb through code for places where to use it
5969 // point = localToWorld(jointPos(leftfoot))
5970 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5971 // adjust height of foot
5972 heightleft = terrain.getHeight(point.x, point.z) + .04;
5973 point.y = heightleft;
5974 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5975 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5976 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5977 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5978 // move ankle along with foot
5979 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5980 // average knee pos between old and new pos
5981 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5983 // do same as above for right leg
5984 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5985 heightright = terrain.getHeight(point.x, point.z) + .04;
5986 point.y = heightright;
5987 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5988 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5989 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5990 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5991 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5993 // fix up skeleton now that we've moved body parts?
5994 p->skeleton.DoConstraints(&p->coords, &p->scale);
6001 int Person::DrawSkeleton()
6003 int oldplayerdetail;
6004 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6005 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6015 glAlphaFunc(GL_GREATER, 0.0001);
6017 float terrainheight;
6021 if (!isnormal(tilt))
6023 if (!isnormal(tilt2))
6025 oldplayerdetail = playerdetail;
6027 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6030 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6033 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6038 if (playerdetail != oldplayerdetail) {
6040 normalsupdatedelay = 0;
6042 static float updatedelaychange;
6043 static float morphness;
6044 static float framemult;
6046 skeleton.FindForwards();
6047 if (howactive == typesittingwall) {
6048 skeleton.specialforward[1] = 0;
6049 skeleton.specialforward[1].z = 1;
6055 static int weaponattachmuscle;
6056 static int weaponrotatemuscle;
6057 static XYZ weaponpoint;
6058 static int start, endthing;
6059 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6060 if (!isSleeping() && !isSitting()) {
6061 // TODO: give these meaningful names
6062 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6063 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6064 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6065 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6067 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6069 if (creature == wolftype)
6073 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6074 IKHelper(this, target);
6075 if (creature == wolftype)
6076 IKHelper(this, target);
6079 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6080 IKHelper(this, 1 - target);
6081 if (creature == wolftype)
6082 IKHelper(this, 1 - target);
6086 if (!skeleton.free && (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || targetFrame().label == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
6089 targetheadyaw = -targetyaw;
6090 targetheadpitch = 0;
6091 if (Animation::animations[animTarget].attack == 3)
6092 targetheadyaw += 180;
6094 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6095 skeleton.drawmodel.vertex[i] = 0;
6096 skeleton.drawmodel.vertex[i].y = 999;
6098 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6099 skeleton.drawmodellow.vertex[i] = 0;
6100 skeleton.drawmodellow.vertex[i].y = 999;
6102 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6103 skeleton.drawmodelclothes.vertex[i] = 0;
6104 skeleton.drawmodelclothes.vertex[i].y = 999;
6106 for (int i = 0; i < skeleton.muscles.size(); i++) {
6107 // convenience renames
6108 const int p1 = skeleton.muscles[i].parent1->label;
6109 const int p2 = skeleton.muscles[i].parent2->label;
6111 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6116 if (p1 == righthand || p2 == righthand) {
6117 morphness = righthandmorphness;
6118 start = righthandmorphstart;
6119 endthing = righthandmorphend;
6121 if (p1 == lefthand || p2 == lefthand) {
6122 morphness = lefthandmorphness;
6123 start = lefthandmorphstart;
6124 endthing = lefthandmorphend;
6126 if (p1 == head || p2 == head) {
6127 morphness = headmorphness;
6128 start = headmorphstart;
6129 endthing = headmorphend;
6131 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6132 morphness = chestmorphness;
6133 start = chestmorphstart;
6134 endthing = chestmorphend;
6136 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6137 morphness = tailmorphness;
6138 start = tailmorphstart;
6139 endthing = tailmorphend;
6142 skeleton.FindRotationMuscle(i, animTarget);
6143 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6144 glMatrixMode(GL_MODELVIEW);
6148 glRotatef(tilt2, 1, 0, 0);
6150 glRotatef(tilt, 0, 0, 1);
6153 glTranslatef(mid.x, mid.y, mid.z);
6155 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6156 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6158 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6159 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6161 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6162 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6164 if (playerdetail || skeleton.free == 3) {
6165 for (j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6166 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6167 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6168 glMatrixMode(GL_MODELVIEW);
6170 if (p1 == abdomen || p2 == abdomen)
6171 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6172 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6173 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6174 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6175 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6176 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6177 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6178 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6179 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6180 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6181 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6182 if (p1 == head || p2 == head)
6183 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6184 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6185 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6186 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6187 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6188 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6189 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6193 if (!playerdetail || skeleton.free == 3) {
6194 for (j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6195 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6196 glMatrixMode(GL_MODELVIEW);
6198 if (p1 == abdomen || p2 == abdomen)
6199 glTranslatef(v0.x * proportionbody.x,
6200 v0.y * proportionbody.y,
6201 v0.z * proportionbody.z);
6202 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6203 glTranslatef(v0.x * proportionarms.x,
6204 v0.y * proportionarms.y,
6205 v0.z * proportionarms.z);
6206 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6207 glTranslatef(v0.x * proportionlegs.x,
6208 v0.y * proportionlegs.y,
6209 v0.z * proportionlegs.z);
6210 if (p1 == head || p2 == head)
6211 glTranslatef(v0.x * proportionhead.x,
6212 v0.y * proportionhead.y,
6213 v0.z * proportionhead.z);
6215 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6216 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6217 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6218 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6224 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6225 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6227 glMatrixMode(GL_MODELVIEW);
6231 glRotatef(tilt2, 1, 0, 0);
6233 glRotatef(tilt, 0, 0, 1);
6234 glTranslatef(mid.x, mid.y, mid.z);
6235 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6236 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6238 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6239 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6241 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6242 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6244 for (j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6245 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6246 glMatrixMode(GL_MODELVIEW);
6248 if (p1 == abdomen || p2 == abdomen)
6249 glTranslatef(v0.x * proportionbody.x,
6250 v0.y * proportionbody.y,
6251 v0.z * proportionbody.z);
6252 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6253 glTranslatef(v0.x * proportionarms.x,
6254 v0.y * proportionarms.y,
6255 v0.z * proportionarms.z);
6256 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6257 glTranslatef(v0.x * proportionlegs.x,
6258 v0.y * proportionlegs.y,
6259 v0.z * proportionlegs.z);
6260 if (p1 == head || p2 == head)
6261 glTranslatef(v0.x * proportionhead.x,
6262 v0.y * proportionhead.y,
6263 v0.z * proportionhead.z);
6264 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6265 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6266 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6267 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6272 updatedelay = 1 + (float)(Random() % 100) / 1000;
6274 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6275 normalsupdatedelay = 1;
6276 if (playerdetail || skeleton.free == 3)
6277 skeleton.drawmodel.CalculateNormals(0);
6278 if (!playerdetail || skeleton.free == 3)
6279 skeleton.drawmodellow.CalculateNormals(0);
6280 if (skeleton.clothes)
6281 skeleton.drawmodelclothes.CalculateNormals(0);
6283 if (playerdetail || skeleton.free == 3)
6284 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6285 if (!playerdetail || skeleton.free == 3)
6286 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6287 if (skeleton.clothes) {
6288 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6293 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6294 if (updatedelaychange > -realmultiplier * 30)
6295 updatedelaychange = -realmultiplier * 30;
6296 if (updatedelaychange > -framemult * 4)
6297 updatedelaychange = -framemult * 4;
6298 if (skeleton.free == 1)
6299 updatedelaychange *= 6;
6301 updatedelaychange *= 8;
6302 updatedelay += updatedelaychange;
6304 glMatrixMode(GL_MODELVIEW);
6306 glTranslatef(coords.x, coords.y - .02, coords.z);
6307 if (!skeleton.free) {
6308 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6309 glRotatef(yaw, 0, 1, 0);
6313 glColor4f(.4, 1, .4, 1);
6314 glDisable(GL_LIGHTING);
6315 glDisable(GL_TEXTURE_2D);
6318 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6319 XYZ &v0 = skeleton.drawmodel.vertex[i];
6320 glVertex3f(v0.x, v0.y, v0.z);
6326 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6327 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6328 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6329 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6330 glVertex3f(v0.x, v0.y, v0.z);
6331 glVertex3f(v1.x, v1.y, v1.z);
6332 glVertex3f(v1.x, v1.y, v1.z);
6333 glVertex3f(v2.x, v2.y, v2.z);
6334 glVertex3f(v2.x, v2.y, v2.z);
6335 glVertex3f(v0.x, v0.y, v0.z);
6341 terrainlight = terrain.getLighting(coords.x, coords.z);
6342 distance = distsq(&viewer, &coords);
6343 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6347 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6348 if (terrainheight < 1)
6350 if (terrainheight > 1.7)
6351 terrainheight = 1.7;
6353 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6354 glDisable(GL_BLEND);
6355 glAlphaFunc(GL_GREATER, 0.0001);
6356 glEnable(GL_TEXTURE_2D);
6358 glDisable(GL_TEXTURE_2D);
6359 glColor4f(.7, .35, 0, .5);
6361 glEnable(GL_LIGHTING);
6364 if (tutoriallevel && id != 0) {
6365 glColor4f(.7, .7, .7, 0.6);
6367 glEnable(GL_LIGHTING);
6369 if (canattack && cananger)
6370 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6371 glDisable(GL_TEXTURE_2D);
6372 glColor4f(1, 0, 0, 0.8);
6374 glMatrixMode(GL_TEXTURE);
6376 glTranslatef(0, -smoketex, 0);
6377 glTranslatef(-smoketex, 0, 0);
6381 if ((tutoriallevel && id != 0))
6382 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6384 skeleton.drawmodel.draw();
6387 if (!playerdetail) {
6388 if ((tutoriallevel && id != 0))
6389 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6391 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6394 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6395 if (tutoriallevel && id != 0) {
6397 glMatrixMode(GL_MODELVIEW);
6398 glEnable(GL_TEXTURE_2D);
6399 glColor4f(.7, .7, .7, 0.6);
6401 glEnable(GL_LIGHTING);
6403 if (canattack && cananger)
6404 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6405 glDisable(GL_TEXTURE_2D);
6406 glColor4f(1, 0, 0, 0.8);
6408 glMatrixMode(GL_TEXTURE);
6410 glTranslatef(0, -smoketex * .6, 0);
6411 glTranslatef(smoketex * .6, 0, 0);
6414 if ((tutoriallevel && id != 0))
6415 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6417 skeleton.drawmodel.draw();
6420 if (!playerdetail) {
6421 if ((tutoriallevel && id != 0))
6422 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6424 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6429 if (tutoriallevel && id != 0) {
6431 glMatrixMode(GL_MODELVIEW);
6432 glEnable(GL_TEXTURE_2D);
6434 if (skeleton.clothes) {
6438 skeleton.drawmodelclothes.draw();
6440 skeleton.drawmodelclothes.drawimmediate();
6446 if (num_weapons > 0) {
6447 for (k = 0; k < num_weapons; k++) {
6449 if (weaponactive == k) {
6450 if (weapons[i].getType() != staff) {
6451 for (j = 0; j < skeleton.muscles.size(); j++) {
6452 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6453 weaponattachmuscle = j;
6456 for (j = 0; j < skeleton.muscles.size(); j++) {
6457 if ((skeleton.muscles[j].parent1->label == rightwrist || skeleton.muscles[j].parent2->label == rightwrist) && (skeleton.muscles[j].parent1->label != righthand && skeleton.muscles[j].parent2->label != righthand) && skeleton.muscles[j].vertices.size() > 0) {
6458 weaponrotatemuscle = j;
6461 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6462 if (creature == wolftype)
6463 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6465 if (weapons[i].getType() == staff) {
6466 for (j = 0; j < skeleton.muscles.size(); j++) {
6467 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6468 weaponattachmuscle = j;
6471 for (j = 0; j < skeleton.muscles.size(); j++) {
6472 if ((skeleton.muscles[j].parent1->label == rightelbow || skeleton.muscles[j].parent2->label == rightelbow) && (skeleton.muscles[j].parent1->label != rightshoulder && skeleton.muscles[j].parent2->label != rightshoulder) && skeleton.muscles[j].vertices.size() > 0) {
6473 weaponrotatemuscle = j;
6476 //weaponpoint=jointPos(rightwrist);
6477 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6478 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6479 XYZ tempnormthing, vec1, vec2;
6480 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6481 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6482 CrossProduct(&vec1, &vec2, &tempnormthing);
6483 Normalise(&tempnormthing);
6484 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6485 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6488 if (weaponactive != k && weaponstuck != k) {
6489 if (weapons[i].getType() == knife)
6490 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6491 if (weapons[i].getType() == sword)
6492 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6493 if (weapons[i].getType() == staff)
6494 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6495 for (j = 0; j < skeleton.muscles.size(); j++) {
6496 if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].vertices.size() > 0) {
6497 weaponrotatemuscle = j;
6501 if (weaponstuck == k) {
6502 if (weaponstuckwhere == 0)
6503 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6505 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6506 for (j = 0; j < skeleton.muscles.size(); j++) {
6507 if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].vertices.size() > 0) {
6508 weaponrotatemuscle = j;
6512 if (skeleton.free) {
6513 weapons[i].position = weaponpoint * scale + coords;
6514 weapons[i].bigrotation = 0;
6515 weapons[i].bigtilt = 0;
6516 weapons[i].bigtilt2 = 0;
6518 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;
6519 weapons[i].bigrotation = yaw;
6520 weapons[i].bigtilt = tilt;
6521 weapons[i].bigtilt2 = tilt2;
6523 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6524 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6525 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6526 if (weaponactive == k) {
6527 if (weapons[i].getType() == knife) {
6528 weapons[i].smallrotation = 180;
6529 weapons[i].smallrotation2 = 0;
6530 if (isCrouch() || wasCrouch()) {
6531 weapons[i].smallrotation2 = 20;
6533 if (animTarget == hurtidleanim) {
6534 weapons[i].smallrotation2 = 50;
6536 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6537 XYZ temppoint1, temppoint2;
6540 temppoint1 = jointPos(righthand);
6541 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6542 distance = findDistance(&temppoint1, &temppoint2);
6543 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6544 weapons[i].rotation2 *= 360 / 6.28;
6547 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6548 weapons[i].rotation1 *= 360 / 6.28;
6549 weapons[i].rotation3 = 0;
6550 weapons[i].smallrotation = -90;
6551 weapons[i].smallrotation2 = 0;
6552 if (temppoint1.x > temppoint2.x)
6553 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6555 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6556 XYZ temppoint1, temppoint2;
6559 temppoint1 = jointPos(righthand);
6560 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6561 distance = findDistance(&temppoint1, &temppoint2);
6562 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6563 weapons[i].rotation2 *= 360 / 6.28;
6566 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6567 weapons[i].rotation1 *= 360 / 6.28;
6568 weapons[i].rotation3 = 0;
6569 weapons[i].smallrotation = 90;
6570 weapons[i].smallrotation2 = 0;
6571 if (temppoint1.x > temppoint2.x)
6572 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6574 if (animTarget == knifethrowanim) {
6575 weapons[i].smallrotation = 90;
6576 //weapons[i].smallrotation2=-90;
6577 weapons[i].smallrotation2 = 0;
6578 weapons[i].rotation1 = 0;
6579 weapons[i].rotation2 = 0;
6580 weapons[i].rotation3 = 0;
6582 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6583 weapons[i].smallrotation = -90;
6584 weapons[i].rotation1 = 0;
6585 weapons[i].rotation2 = 0;
6586 weapons[i].rotation3 = 0;
6589 if (weapons[i].getType() == sword) {
6590 weapons[i].smallrotation = 0;
6591 weapons[i].smallrotation2 = 0;
6592 if (animTarget == knifethrowanim) {
6593 weapons[i].smallrotation = -90;
6594 weapons[i].smallrotation2 = 0;
6595 weapons[i].rotation1 = 0;
6596 weapons[i].rotation2 = 0;
6597 weapons[i].rotation3 = 0;
6599 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)) {
6600 XYZ temppoint1, temppoint2;
6603 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6604 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6605 distance = findDistance(&temppoint1, &temppoint2);
6606 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6607 weapons[i].rotation2 *= 360 / 6.28;
6610 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6611 weapons[i].rotation1 *= 360 / 6.28;
6612 weapons[i].rotation3 = 0;
6613 weapons[i].smallrotation = 90;
6614 weapons[i].smallrotation2 = 0;
6615 if (temppoint1.x > temppoint2.x)
6616 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6619 if (weapons[i].getType() == staff) {
6620 weapons[i].smallrotation = 100;
6621 weapons[i].smallrotation2 = 0;
6622 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6623 XYZ temppoint1, temppoint2;
6626 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6627 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6628 distance = findDistance(&temppoint1, &temppoint2);
6629 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6630 weapons[i].rotation2 *= 360 / 6.28;
6633 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6634 weapons[i].rotation1 *= 360 / 6.28;
6635 weapons[i].rotation3 = 0;
6636 weapons[i].smallrotation = 90;
6637 weapons[i].smallrotation2 = 0;
6638 if (temppoint1.x > temppoint2.x)
6639 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6643 if (weaponactive != k && weaponstuck != k) {
6644 if (weapons[i].getType() == knife) {
6645 weapons[i].smallrotation = -70;
6646 weapons[i].smallrotation2 = 10;
6648 if (weapons[i].getType() == sword) {
6649 weapons[i].smallrotation = -100;
6650 weapons[i].smallrotation2 = -8;
6652 if (weapons[i].getType() == staff) {
6653 weapons[i].smallrotation = -100;
6654 weapons[i].smallrotation2 = -8;
6657 if (weaponstuck == k) {
6658 if (weaponstuckwhere == 0)
6659 weapons[i].smallrotation = 180;
6661 weapons[i].smallrotation = 0;
6662 weapons[i].smallrotation2 = 10;
6671 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6673 if (animCurrent != animTarget)
6675 if (skeleton.free == 2)
6684 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6687 static float distance;
6688 static float olddistance;
6689 static int intersecting;
6690 static int firstintersecting;
6693 static XYZ start, end;
6694 static float slopethreshold = -.4;
6696 firstintersecting = -1;
6700 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6703 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6704 for (i = 0; i < 4; i++) {
6705 for (j = 0; j < model->TriangleNum; j++) {
6706 if (model->facenormals[j].y <= slopethreshold) {
6708 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)));
6709 if (distance < radius) {
6710 point = *p1 - model->facenormals[j] * distance;
6711 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]]))
6714 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6715 &model->vertex[model->Triangles[j].vertex[1]],
6718 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6719 &model->vertex[model->Triangles[j].vertex[2]],
6722 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6723 &model->vertex[model->Triangles[j].vertex[2]],
6726 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6730 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)) {
6731 p1->y = point.y + radius;
6732 if ((animTarget == jumpdownanim || isFlip())) {
6733 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6736 if (animTarget == jumpupanim) {
6738 animTarget = getIdle();
6745 pause_sound(whooshsound);
6746 OPENAL_SetVolume(channels[whooshsound], 0);
6749 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6752 animTarget = getLanding();
6753 emit_sound_at(landsound, coords, 128.);
6756 addEnvSound(coords);
6763 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6764 olddistance = distance;
6765 firstintersecting = j;
6770 for (j = 0; j < model->TriangleNum; j++) {
6771 if (model->facenormals[j].y > slopethreshold) {
6774 start.y -= radius / 4;
6775 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6776 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6777 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6778 distance = abs((model->facenormals[j].x * start.x)
6779 + (model->facenormals[j].y * start.y)
6780 + (model->facenormals[j].z * start.z)
6781 - ((model->facenormals[j].x * v0.x)
6782 + (model->facenormals[j].y * v0.y)
6783 + (model->facenormals[j].z * v0.z)));
6784 if (distance < radius * .5) {
6785 point = start - model->facenormals[j] * distance;
6786 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6789 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6791 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6793 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6795 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6796 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6798 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6799 if (findLengthfast(&start) < findLengthfast(&velocity))
6802 *p1 += model->facenormals[j] * (distance - radius * .5);
6805 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6806 olddistance = distance;
6807 firstintersecting = j;
6814 *p = DoRotation(*p, 0, *rotate, 0);
6817 *p1 = DoRotation(*p1, 0, *rotate, 0);
6819 return firstintersecting;
6822 void Person::takeWeapon(int weaponId)
6825 weapons[weaponId].owner = id;
6826 if (num_weapons > 0) {
6827 weaponids[num_weapons] = weaponids[0];
6830 weaponids[0] = weaponId;
6833 void Person::addClothes()
6835 if (numclothes > 0) {
6836 for (int i = 0; i < numclothes; i++) {
6843 bool Person::addClothes(const int& clothesId)
6846 const std::string fileName = clothes[clothesId];
6848 GLubyte* array = &skeleton.skinText[0];
6852 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6857 float tintr = clothestintr[clothesId];
6858 float tintg = clothestintg[clothesId];
6859 float tintb = clothestintb[clothesId];
6861 if (tintr > 1) tintr = 1;
6862 if (tintg > 1) tintg = 1;
6863 if (tintb > 1) tintb = 1;
6865 if (tintr < 0) tintr = 0;
6866 if (tintg < 0) tintg = 0;
6867 if (tintb < 0) tintb = 0;
6869 int bytesPerPixel = texture.bpp / 8;
6873 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6874 if (bytesPerPixel == 3)
6876 else if ((i + 1) % 4 == 0)
6877 alphanum = texture.data[i];
6878 if ((i + 1) % 4 || bytesPerPixel == 3) {
6880 texture.data[i] *= tintr;
6882 texture.data[i] *= tintg;
6884 texture.data[i] *= tintb;
6885 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);