2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation.h"
29 #include "Utils/Folders.h"
31 extern float multiplier;
32 extern Terrain terrain;
34 extern int environment;
36 extern FRUSTUM frustum;
38 extern float realmultiplier;
40 extern float slomodelay;
41 extern bool cellophane;
42 extern float texdetail;
43 extern float realtexdetail;
44 extern GLubyte bloodText[512 * 512 * 3];
45 extern GLubyte wolfbloodText[512 * 512 * 3];
46 extern int bloodtoggle;
47 extern Objects objects;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern int tutoriallevel;
61 extern float smoketex;
62 extern int tutorialstage;
63 extern bool reversaltrain;
64 extern bool canattack;
66 extern float damagedealt;
68 extern float hostiletime;
70 extern bool gamestarted;
72 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
77 animCurrent(bounceidleanim),
78 animTarget(bounceidleanim),
85 howactive(typeactive),
87 superruntoggle(false),
88 lastattack(0), lastattack2(0), lastattack3(0),
89 currentoffset(), targetoffset(), offset(),
121 rabbitkickenabled(false),
130 damagetolerance(200),
133 superpermanentdamage(0),
147 bleedx(0), bleedy(0),
151 headyaw(0), headpitch(0),
152 targetheadyaw(0), targetheadpitch(0),
163 normalsupdatedelay(0),
166 forwardkeydown(false),
167 forwardstogglekeydown(false),
172 jumptogglekeydown(false),
173 crouchkeydown(false),
174 crouchtogglekeydown(false),
176 drawtogglekeydown(false),
178 throwtogglekeydown(false),
179 attackkeydown(false),
184 crouchkeydowntime(0),
198 whichdirection(false),
199 whichdirectiondelay(0),
200 avoidsomething(false),
209 lefthandmorphness(0),
210 righthandmorphness(0),
214 targetlefthandmorphness(0),
215 targetrighthandmorphness(0),
216 targetheadmorphness(1),
217 targetchestmorphness(0),
218 targettailmorphness(0),
219 lefthandmorphstart(0), lefthandmorphend(0),
220 righthandmorphstart(0), righthandmorphend(0),
221 headmorphstart(0), headmorphend(0),
222 chestmorphstart(0), chestmorphend(0),
223 tailmorphstart(0), tailmorphend(0),
226 highreversaldelay(0),
229 creature(rabbittype),
276 finalpathfindpoint(0),
277 targetpathfindpoint(0),
278 lastpathfindpoint(0),
279 lastpathfindpoint2(0),
280 lastpathfindpoint3(0),
281 lastpathfindpoint4(0),
298 neckspurtparticledelay(0),
302 rabbitkickragdoll(false),
310 /* Read a person in tfile. Throws an error if it’s not valid */
311 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
314 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
316 funpackf(tfile, "Bi", &howactive);
318 howactive = typeactive;
321 funpackf(tfile, "Bf", &scale);
326 funpackf(tfile, "Bb", &immobile);
331 funpackf(tfile, "Bf", &yaw);
336 if (num_weapons < 0 || num_weapons > 5) {
337 throw InvalidPersonException();
339 if (num_weapons > 0 && num_weapons < 5) {
340 for (int j = 0; j < num_weapons; j++) {
341 weaponids[j] = weapons.size();
343 funpackf(tfile, "Bi", &type);
344 weapons.push_back(Weapon(type, id));
347 funpackf(tfile, "Bi", &numwaypoints);
348 for (int j = 0; j < numwaypoints; j++) {
349 funpackf(tfile, "Bf", &waypoints[j].x);
350 funpackf(tfile, "Bf", &waypoints[j].y);
351 funpackf(tfile, "Bf", &waypoints[j].z);
353 funpackf(tfile, "Bi", &waypointtype[j]);
355 waypointtype[j] = wpkeepwalking;
359 funpackf(tfile, "Bi", &waypoint);
360 if (waypoint > (numwaypoints - 1)) {
364 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
365 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
366 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
367 funpackf(tfile, "Bf Bf", &power, &speedmult);
369 float headprop, legprop, armprop, bodyprop;
372 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
380 if (creature == wolftype) {
381 proportionhead = 1.1 * headprop;
382 proportionbody = 1.1 * bodyprop;
383 proportionarms = 1.1 * armprop;
384 proportionlegs = 1.1 * legprop;
385 } else if (creature == rabbittype) {
386 proportionhead = 1.2 * headprop;
387 proportionbody = 1.05 * bodyprop;
388 proportionarms = 1.00 * armprop;
389 proportionlegs = 1.1 * legprop;
390 proportionlegs.y = 1.05 * legprop;
393 funpackf(tfile, "Bi", &numclothes);
394 for (int k = 0; k < numclothes; k++) {
396 funpackf(tfile, "Bi", &templength);
397 for (int l = 0; l < templength; l++)
398 funpackf(tfile, "Bb", &clothes[k][l]);
399 clothes[k][templength] = '\0';
400 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
406 if (creature == wolftype) {
408 damagetolerance = 300;
415 realoldcoords = coords;
421 * GameTick/doPlayerCollisions
423 void Person::CheckKick()
426 && (animTarget == rabbitkickanim
428 && victim != this->shared_from_this()
430 && animCurrent == rabbitkickanim)
431 && distsq(&coords, &victim->coords) < 1.2
432 && !victim->skeleton.free))
435 if (animation[victim->animTarget].height != lowheight) {
436 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
437 XYZ relative = velocity;
439 Normalise(&relative);
443 if (tutoriallevel != 1)
444 emit_sound_at(heavyimpactsound, victim->coords);
446 for (int i = 0; i < victim->skeleton.num_joints; i++) {
447 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
450 victim->DoDamage(100 * damagemult / victim->protectionhigh);
456 animTarget = backflipanim;
458 velocity = facing * -10;
462 resume_stream(whooshsound);
464 award_bonus(id, cannon);
465 } else if (victim->isCrouch()) {
466 animTarget = rabbitkickreversedanim;
467 animCurrent = rabbitkickreversedanim;
468 victim->animCurrent = rabbitkickreversalanim;
469 victim->animTarget = rabbitkickreversalanim;
475 victim->oldcoords = victim->coords;
476 coords = victim->coords;
477 victim->targetyaw = targetyaw;
478 victim->victim = this->shared_from_this();
485 * GameTick/doPlayerCollisions - spread fire between players
486 * GameTick/doDebugKeys - press f to ignite
487 * Person::DoStuff - spread fire from lit campfires and bushes
489 void Person::CatchFire()
491 XYZ flatfacing, flatvelocity;
493 for (int i = 0; i < 10; i++) {
494 howmany = abs(Random() % (skeleton.num_joints));
496 flatvelocity = skeleton.joints[howmany].velocity;
497 flatfacing = skeleton.joints[howmany].position * scale + coords;
499 flatvelocity = velocity;
500 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
502 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
507 emit_sound_at(firestartsound, coords);
509 emit_stream_at(stream_firesound, coords);
517 * idle animation for this creature (depending on status)
519 int Person::getIdle()
521 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
523 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
524 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
525 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
526 victim->id < Person::players.size())) {
527 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
528 if (creature == rabbittype)
529 return fightidleanim;
530 if (creature == wolftype)
533 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
534 if (weapons[weaponids[weaponactive]].getType() == knife)
535 return knifefightidleanim;
536 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
537 return swordfightidlebothanim;
538 if (weapons[weaponids[weaponactive]].getType() == sword)
539 return swordfightidleanim;
540 if (weapons[weaponids[weaponactive]].getType() == staff)
541 return swordfightidleanim;
543 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
544 return fightsidestep;
546 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
548 if (howactive == typesitting) return sitanim;
549 if (howactive == typesittingwall) return sitwallanim;
550 if (howactive == typesleeping) return sleepanim;
551 if (howactive == typedead1) return dead1anim;
552 if (howactive == typedead2) return dead2anim;
553 if (howactive == typedead3) return dead3anim;
554 if (howactive == typedead4) return dead4anim;
555 if (creature == rabbittype) return bounceidleanim;
556 if (creature == wolftype) return wolfidle;
561 * crouch animation for this creature
563 int Person::getCrouch()
565 if (creature == rabbittype)
567 if (creature == wolftype)
568 return wolfcrouchanim;
573 * running animation for this creature (can be upright or all fours)
577 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
579 if (creature == wolftype && (!superruntoggle))
582 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
583 return rabbitrunninganim;
584 if (creature == wolftype && (superruntoggle))
585 return wolfrunninganim;
591 int Person::getStop()
593 if (creature == rabbittype)
595 if (creature == wolftype)
602 int Person::getLanding()
604 if (creature == rabbittype)
606 if (creature == wolftype)
613 int Person::getLandhard()
615 if (creature == rabbittype)
617 if (creature == wolftype)
618 return wolflandhardanim;
625 * Person::DoAnimations
628 SolidHitBonus(int playerid)
630 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
631 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
633 award_bonus(playerid, solidhit);
637 * spawns blood effects
639 void Person::DoBlood(float howmuch, int which)
641 // FIXME: should abstract out inputs
642 static int bleedxint, bleedyint;
644 if (bloodtoggle && tutoriallevel != 1) {
645 if (bleeding <= 0 && spurt) {
647 for (int i = 0; i < 3; i++) {
648 // emit blood particles
651 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
652 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
653 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
654 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
657 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
658 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
659 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
660 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
663 if (Random() % 2 == 0) // 50% chance
664 for (int i = 0; i < 3; i++) {
665 if (Random() % 2 != 0) {
666 // emit teeth particles
669 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
670 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
673 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
674 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
678 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
680 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
682 Sprite::setLastSpriteSpecial(3); // sets it to teeth
687 // FIXME: manipulating attributes
688 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
691 if (creature == rabbittype)
692 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) {
693 bleedxint = abs(Random() % 512);
694 bleedyint = abs(Random() % 512);
696 if (creature == wolftype)
697 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) {
698 bleedxint = abs(Random() % 512);
699 bleedyint = abs(Random() % 512);
703 bleedy /= realtexdetail;
704 bleedx /= realtexdetail;
705 direction = abs(Random() % 2) * 2 - 1;
714 * spawns big blood effects and ???
715 * modifies character's skin texture
717 void Person::DoBloodBig(float howmuch, int which)
719 static int bleedxint, bleedyint, i, j;
721 if (howmuch && id == 0)
724 if (tutoriallevel != 1 || id == 0)
725 if (aitype != playercontrolled && howmuch > 0) {
729 if (creature == wolftype) {
730 int i = abs(Random() % 2);
732 whichsound = snarlsound;
734 whichsound = snarl2sound;
736 if (creature == rabbittype) {
737 int i = abs(Random() % 2);
739 whichsound = rabbitpainsound;
740 if (i == 1 && howmuch >= 2)
741 whichsound = rabbitpain1sound;
744 if (whichsound != -1) {
745 emit_sound_at(whichsound, coords);
750 if (id == 0 && howmuch > 0) {
754 if (bloodtoggle && decals && tutoriallevel != 1) {
755 if (bleeding <= 0 && spurt) {
757 for (int i = 0; i < 3; i++) {
758 // emit blood particles
759 // FIXME: copypaste from above
762 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
763 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
764 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
765 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
768 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
769 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
770 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
771 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
776 // weird texture manipulation code follows.
777 // looks like this is painting blood onto the character's skin texture
778 // FIXME: surely there's a better way
780 int offsetx = 0, offsety = 0;
782 offsety = Random() % 40;
783 offsetx = abs(Random() % 60);
785 if (which == 190 || which == 185) {
786 offsety = Random() % 40;
787 offsetx = abs(Random() % 100) - 20;
790 offsety = Random() % 10;
791 offsetx = Random() % 10;
794 offsety = Random() % 20;
795 offsetx = Random() % 20;
797 if (which == 220 || which == 215) {
807 if (creature == rabbittype)
808 for (i = 0; i < 512; i++) {
809 for (j = 0; j < 512; j++) {
810 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
811 if (i < startx) startx = i;
812 if (j < starty) starty = j;
813 if (i > endx) endx = i;
814 if (j > endy) endy = j;
818 if (creature == wolftype)
819 for (i = 0; i < 512; i++) {
820 for (j = 0; j < 512; j++) {
821 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
822 if (i < startx) startx = i;
823 if (j < starty) starty = j;
824 if (i > endx) endx = i;
825 if (j > endy) endy = j;
835 if (startx < 0) startx = 0;
836 if (starty < 0) starty = 0;
837 if (endx > 512 - 1) endx = 512 - 1;
838 if (endy > 512 - 1) endy = 512 - 1;
839 if (endx < startx) endx = startx;
840 if (endy < starty) endy = starty;
842 startx /= realtexdetail;
843 starty /= realtexdetail;
844 endx /= realtexdetail;
845 endy /= realtexdetail;
847 int texdetailint = realtexdetail;
849 if (creature == rabbittype)
850 for (i = startx; i < endx; i++) {
851 for (j = starty; j < endy; j++) {
852 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) {
853 color = Random() % 85 + 170;
854 where = i * skeleton.skinsize * 3 + j * 3;
855 if (skeleton.skinText[where + 0] > color / 2)
856 skeleton.skinText[where + 0] = color / 2;
857 skeleton.skinText[where + 1] = 0;
858 skeleton.skinText[where + 2] = 0;
862 if (creature == wolftype)
863 for (i = startx; i < endx; i++) {
864 for (j = starty; j < endy; j++) {
865 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) {
866 color = Random() % 85 + 170;
867 where = i * skeleton.skinsize * 3 + j * 3;
868 if (skeleton.skinText[where + 0] > color / 2)
869 skeleton.skinText[where + 0] = color / 2;
870 skeleton.skinText[where + 1] = 0;
871 skeleton.skinText[where + 2] = 0;
875 skeleton.drawmodel.textureptr.bind();
880 if (creature == rabbittype)
881 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) {
882 bleedxint = abs(Random() % 512);
883 bleedyint = abs(Random() % 512);
885 if (creature == wolftype)
886 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) {
887 bleedxint = abs(Random() % 512);
888 bleedyint = abs(Random() % 512);
890 bleedy = bleedxint + offsetx;
891 bleedx = bleedyint + offsety;
892 bleedy /= realtexdetail;
893 bleedx /= realtexdetail;
898 if (bleedx > skeleton.skinsize - 1)
899 bleedx = skeleton.skinsize - 1;
900 if (bleedy > skeleton.skinsize - 1)
901 bleedy = skeleton.skinsize - 1;
902 direction = abs(Random() % 2) * 2 - 1;
905 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
906 deathbleeding += bleeding;
907 bloodloss += bleeding * 3;
909 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
910 if (abs(Random() % 2) == 0) {
911 aitype = gethelptype;
914 aitype = attacktypecutoff;
922 * similar to DoBloodBig
924 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
928 static XYZ startpoint, endpoint, colpoint, movepoint;
929 static float rotationpoint;
931 static XYZ p1, p2, p3, p0;
934 float coordsx, coordsy;
937 if (bloodtoggle && decals && tutoriallevel != 1) {
940 where = DoRotation(where, 0, -yaw, 0);
948 // ray testing for a tri in the character model
949 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
950 if (whichtri != -1) {
951 // low level geometry math
953 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
954 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
955 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
957 bary.x = distsq(&p0, &p1);
958 bary.y = distsq(&p0, &p2);
959 bary.z = distsq(&p0, &p3);
961 total = bary.x + bary.y + bary.z;
970 total = bary.x + bary.y + bary.z;
976 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
977 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
978 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
979 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
980 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
981 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
982 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;
983 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;
985 if (bleeding <= 0 && spurt) {
987 for (int i = 0; i < 3; i++) {
988 // emit blood particles
989 // FIXME: more copypaste code
992 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
993 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
994 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
995 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
998 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
999 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1000 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1001 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1006 // texture manipulation follows
1008 int offsetx = 0, offsety = 0;
1009 offsetx = (1 + coordsy) * 512 - 291;
1010 offsety = coordsx * 512 - 437;
1017 if (creature == rabbittype)
1018 for (i = 0; i < 512; i++) {
1019 for (j = 0; j < 512; j++) {
1020 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1021 if (i < startx) startx = i;
1022 if (j < starty) starty = j;
1023 if (i > endx) endx = i;
1024 if (j > endy) endy = j;
1028 if (creature == wolftype)
1029 for (i = 0; i < 512; i++) {
1030 for (j = 0; j < 512; j++) {
1031 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1032 if (i < startx) startx = i;
1033 if (j < starty) starty = j;
1034 if (i > endx) endx = i;
1035 if (j > endy) endy = j;
1044 if (startx < 0) startx = 0;
1045 if (starty < 0) starty = 0;
1046 if (endx > 512 - 1) endx = 512 - 1;
1047 if (endy > 512 - 1) endy = 512 - 1;
1048 if (endx < startx) endx = startx;
1049 if (endy < starty) endy = starty;
1051 startx /= realtexdetail;
1052 starty /= realtexdetail;
1053 endx /= realtexdetail;
1054 endy /= realtexdetail;
1056 int texdetailint = realtexdetail;
1058 if (creature == rabbittype)
1059 for (i = startx; i < endx; i++) {
1060 for (j = starty; j < endy; j++) {
1061 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) {
1062 color = Random() % 85 + 170;
1063 where = i * skeleton.skinsize * 3 + j * 3;
1064 if (skeleton.skinText[where + 0] > color / 2)
1065 skeleton.skinText[where + 0] = color / 2;
1066 skeleton.skinText[where + 1] = 0;
1067 skeleton.skinText[where + 2] = 0;
1068 } 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) {
1069 color = Random() % 85 + 170;
1070 where = i * skeleton.skinsize * 3 + j * 3;
1071 if (skeleton.skinText[where + 0] > color / 2)
1072 skeleton.skinText[where + 0] = color / 2;
1073 skeleton.skinText[where + 1] = 0;
1074 skeleton.skinText[where + 2] = 0;
1078 if (creature == wolftype)
1079 for (i = startx; i < endx; i++) {
1080 for (j = starty; j < endy; j++) {
1081 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) {
1082 color = Random() % 85 + 170;
1083 where = i * skeleton.skinsize * 3 + j * 3;
1084 if (skeleton.skinText[where + 0] > color / 2)
1085 skeleton.skinText[where + 0] = color / 2;
1086 skeleton.skinText[where + 1] = 0;
1087 skeleton.skinText[where + 2] = 0;
1088 } 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) {
1089 color = Random() % 85 + 170;
1090 where = i * skeleton.skinsize * 3 + j * 3;
1091 if (skeleton.skinText[where + 0] > color / 2)
1092 skeleton.skinText[where + 0] = color / 2;
1093 skeleton.skinText[where + 1] = 0;
1094 skeleton.skinText[where + 2] = 0;
1098 skeleton.drawmodel.textureptr.bind();
1101 bleedy = (1 + coordsy) * 512;
1102 bleedx = coordsx * 512;
1103 bleedy /= realtexdetail;
1104 bleedx /= realtexdetail;
1109 if (bleedx > skeleton.skinsize - 1)
1110 bleedx = skeleton.skinsize - 1;
1111 if (bleedy > skeleton.skinsize - 1)
1112 bleedy = skeleton.skinsize - 1;
1113 direction = abs(Random() % 2) * 2 - 1;
1118 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1119 deathbleeding += bleeding;
1120 bloodloss += bleeding * 3;
1122 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1123 if (abs(Random() % 2) == 0) {
1124 aitype = gethelptype;
1127 aitype = attacktypecutoff;
1138 * guessing this performs a reversal
1140 void Person::Reverse()
1142 if (!((victim->aitype == playercontrolled
1144 || staggerdelay <= 0)
1145 && victim->animTarget != jumpupanim
1146 && victim->animTarget != jumpdownanim
1147 && (tutoriallevel != 1 || cananger)
1151 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1152 && (victim->id != 0 || difficulty >= 2)
1153 && (creature != wolftype || victim->creature == wolftype))
1156 if (animTarget == sweepanim) {
1157 animTarget = sweepreversedanim;
1158 animCurrent = sweepreversedanim;
1159 victim->animCurrent = sweepreversalanim;
1160 victim->animTarget = sweepreversalanim;
1162 if (animTarget == spinkickanim) {
1163 animTarget = spinkickreversedanim;
1164 animCurrent = spinkickreversedanim;
1165 victim->animCurrent = spinkickreversalanim;
1166 victim->animTarget = spinkickreversalanim;
1168 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1169 if (animTarget == rabbittacklinganim) {
1172 victim->frameCurrent = 6;
1173 victim->frameTarget = 7;
1175 animTarget = upunchreversedanim;
1176 animCurrent = upunchreversedanim;
1177 victim->animCurrent = upunchreversalanim;
1178 victim->animTarget = upunchreversalanim;
1180 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1181 if (victim->weaponactive != -1) {
1182 victim->throwtogglekeydown = 1;
1183 XYZ tempVelocity = victim->velocity * .2;
1184 if (tempVelocity.x == 0)
1185 tempVelocity.x = .1;
1186 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1187 victim->num_weapons--;
1188 if (victim->num_weapons) {
1189 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1190 if (victim->weaponstuck == victim->num_weapons)
1191 victim->weaponstuck = 0;
1194 victim->weaponactive = -1;
1195 for (unsigned j = 0; j < Person::players.size(); j++) {
1196 Person::players[j]->wentforweapon = 0;
1200 animTarget = staffhitreversedanim;
1201 animCurrent = staffhitreversedanim;
1202 victim->animCurrent = staffhitreversalanim;
1203 victim->animTarget = staffhitreversalanim;
1205 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1206 if (victim->weaponactive != -1) {
1207 victim->throwtogglekeydown = 1;
1208 XYZ tempVelocity = victim->velocity * .2;
1209 if (tempVelocity.x == 0)
1210 tempVelocity.x = .1;
1211 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1212 victim->num_weapons--;
1213 if (victim->num_weapons) {
1214 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1215 if (victim->weaponstuck == victim->num_weapons)
1216 victim->weaponstuck = 0;
1219 victim->weaponactive = -1;
1220 for (unsigned j = 0; j < Person::players.size(); j++) {
1221 Person::players[j]->wentforweapon = 0;
1224 animTarget = staffspinhitreversedanim;
1225 animCurrent = staffspinhitreversedanim;
1226 victim->animCurrent = staffspinhitreversalanim;
1227 victim->animTarget = staffspinhitreversalanim;
1229 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1230 if (victim->weaponactive != -1) {
1231 victim->throwtogglekeydown = 1;
1232 XYZ tempVelocity = victim->velocity * .2;
1233 if (tempVelocity.x == 0)
1234 tempVelocity.x = .1;
1235 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1236 victim->num_weapons--;
1237 if (victim->num_weapons) {
1238 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1239 if (victim->weaponstuck == victim->num_weapons)
1240 victim->weaponstuck = 0;
1243 victim->weaponactive = -1;
1244 for (unsigned j = 0; j < Person::players.size(); j++) {
1245 Person::players[j]->wentforweapon = 0;
1248 animTarget = swordslashreversedanim;
1249 animCurrent = swordslashreversedanim;
1250 victim->animCurrent = swordslashreversalanim;
1251 victim->animTarget = swordslashreversalanim;
1253 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1254 if (victim->weaponactive != -1) {
1255 victim->throwtogglekeydown = 1;
1256 XYZ tempVelocity = victim->velocity * .2;
1257 if (tempVelocity.x == 0)
1258 tempVelocity.x = .1;
1259 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1260 victim->num_weapons--;
1261 if (victim->num_weapons) {
1262 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1263 if (victim->weaponstuck == victim->num_weapons)
1264 victim->weaponstuck = 0;
1267 victim->weaponactive = -1;
1268 for (unsigned j = 0; j < Person::players.size(); j++) {
1269 Person::players[j]->wentforweapon = 0;
1272 animTarget = knifeslashreversedanim;
1273 animCurrent = knifeslashreversedanim;
1274 victim->animCurrent = knifeslashreversalanim;
1275 victim->animTarget = knifeslashreversalanim;
1277 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1278 victim->targettilt2 = targettilt2;
1279 victim->frameCurrent = frameCurrent;
1280 victim->frameTarget = frameTarget;
1281 victim->target = target;
1282 victim->velocity = 0;
1283 victim->oldcoords = victim->coords;
1284 victim->coords = coords;
1285 victim->targetyaw = targetyaw;
1286 victim->yaw = targetyaw;
1287 victim->victim = this->shared_from_this();
1289 if (animTarget == winduppunchanim) {
1290 animTarget = winduppunchblockedanim;
1291 victim->animTarget = blockhighleftanim;
1292 victim->frameTarget = 1;
1293 victim->target = .5;
1294 victim->victim = this->shared_from_this();
1295 victim->targetyaw = targetyaw + 180;
1297 if (animTarget == wolfslapanim) {
1298 animTarget = winduppunchblockedanim;
1299 victim->animTarget = blockhighleftanim;
1300 victim->frameTarget = 1;
1301 victim->target = .5;
1302 victim->victim = this->shared_from_this();
1303 victim->targetyaw = targetyaw + 180;
1305 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1306 animTarget = swordslashparriedanim;
1307 parriedrecently = .4;
1308 victim->parriedrecently = 0;
1309 victim->animTarget = swordslashparryanim;
1310 victim->frameTarget = 1;
1311 victim->target = .5;
1312 victim->victim = this->shared_from_this();
1313 victim->targetyaw = targetyaw + 180;
1315 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1316 if (victim->weaponactive != -1) {
1317 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1318 if (weapons[victim->weaponids[0]].getType() == staff)
1319 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1320 if (weapons[weaponids[0]].getType() == staff)
1321 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1322 emit_sound_at(swordstaffsound, victim->coords);
1324 emit_sound_at(metalhitsound, victim->coords);
1328 victim->Puff(righthand);
1330 victim->frameTarget = 0;
1331 victim->animTarget = staggerbackhighanim;
1332 victim->targetyaw = targetyaw + 180;
1334 aim = DoRotation(facing, 0, 90, 0) * 21;
1336 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1337 victim->num_weapons--;
1338 if (victim->num_weapons) {
1339 victim->weaponids[0] = victim->weaponids[num_weapons];
1340 if (victim->weaponstuck == victim->num_weapons)
1341 victim->weaponstuck = 0;
1343 victim->weaponactive = -1;
1344 for (unsigned i = 0; i < Person::players.size(); i++) {
1345 Person::players[i]->wentforweapon = 0;
1349 if (abs(Random() % 20) == 0) {
1350 if (weaponactive != -1) {
1351 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1352 if (weapons[victim->weaponids[0]].getType() == staff)
1353 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1354 if (weapons[weaponids[0]].getType() == staff)
1355 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1357 emit_sound_at(swordstaffsound, coords);
1359 emit_sound_at(metalhitsound, coords);
1367 animTarget = staggerbackhighanim;
1368 targetyaw = targetyaw + 180;
1370 aim = DoRotation(facing, 0, 90, 0) * 21;
1372 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1375 weaponids[0] = weaponids[num_weapons];
1376 if (weaponstuck == num_weapons)
1380 for (unsigned i = 0; i < Person::players.size(); i++) {
1381 Person::players[i]->wentforweapon = 0;
1388 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1389 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1390 victim->animTarget = dodgebackanim;
1391 victim->frameTarget = 0;
1395 rotatetarget = coords - victim->coords;
1396 Normalise(&rotatetarget);
1397 victim->targetyaw = -asin(0 - rotatetarget.x);
1398 victim->targetyaw *= 360 / 6.28;
1399 if (rotatetarget.z < 0)
1400 victim->targetyaw = 180 - victim->targetyaw;
1402 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1404 victim->lastattack3 = victim->lastattack2;
1405 victim->lastattack2 = victim->lastattack;
1406 victim->lastattack = victim->animTarget;
1408 victim->animTarget = sweepanim;
1409 victim->frameTarget = 0;
1413 rotatetarget = coords - victim->coords;
1414 Normalise(&rotatetarget);
1415 victim->targetyaw = -asin(0 - rotatetarget.x);
1416 victim->targetyaw *= 360 / 6.28;
1417 if (rotatetarget.z < 0)
1418 victim->targetyaw = 180 - victim->targetyaw;
1420 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1422 victim->lastattack3 = victim->lastattack2;
1423 victim->lastattack2 = victim->lastattack;
1424 victim->lastattack = victim->animTarget;
1429 victim->velocity = 0;
1431 if (aitype != playercontrolled)
1433 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1435 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1437 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1440 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1447 void Person::DoDamage(float howmuch)
1449 // subtract health (temporary?)
1450 if (tutoriallevel != 1)
1451 damage += howmuch / power;
1454 damagedealt += howmuch / power;
1456 damagetaken += howmuch / power;
1459 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1462 if (tutoriallevel != 1)
1463 permanentdamage += howmuch / 2 / power;
1464 if (tutoriallevel != 1)
1465 superpermanentdamage += howmuch / 4 / power;
1467 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1469 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1473 camerashake += howmuch / 100;
1474 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1475 blackout = damage / damagetolerance;
1480 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1481 aitype = attacktypecutoff;
1482 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1483 if (abs(Random() % 2) == 0) {
1484 aitype = gethelptype;
1487 aitype = attacktypecutoff;
1491 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1494 for (int i = 0; i < skeleton.num_joints; i++) {
1495 if (skeleton.free) {
1496 flatvelocity2 = skeleton.joints[i].velocity;
1497 flatfacing2 = skeleton.joints[i].position * scale + coords;
1499 flatvelocity2 = velocity;
1500 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1502 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1503 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1504 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1505 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1506 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1507 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1510 emit_sound_at(splattersound, coords);
1515 if (!dead && creature == wolftype) {
1516 award_bonus(0, Wolfbonus);
1523 if (tutoriallevel != 1 || id == 0)
1524 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1525 int whichsound = -1;
1527 if (creature == wolftype) {
1528 int i = abs(Random() % 2);
1530 whichsound = snarlsound;
1532 whichsound = snarl2sound;
1534 if (creature == rabbittype) {
1535 int i = abs(Random() % 2);
1537 whichsound = rabbitpainsound;
1538 if (i == 1 && damage > damagetolerance)
1539 whichsound = rabbitpain1sound;
1542 if (whichsound != -1) {
1543 emit_sound_at(whichsound, coords);
1544 addEnvSound(coords);
1551 * calculate/animate head facing direction?
1553 void Person::DoHead()
1555 static XYZ rotatearound;
1557 static float lookspeed = 500;
1559 if (!freeze && !winfreeze) {
1562 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1563 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1565 while (targetheadyaw > 180)targetheadyaw -= 360;
1566 while (targetheadyaw < -180)targetheadyaw += 360;
1568 if (targetheadyaw > 160)
1569 targetheadpitch = targetheadpitch * -1;
1570 if (targetheadyaw < -160)
1571 targetheadpitch = targetheadpitch * -1;
1572 if (targetheadyaw > 160)
1573 targetheadyaw = targetheadyaw - 180;
1574 if (targetheadyaw < -160)
1575 targetheadyaw = targetheadyaw + 180;
1577 if (targetheadpitch > 120)
1578 targetheadpitch = 120;
1579 if (targetheadpitch < -120)
1580 targetheadpitch = -120;
1581 if (targetheadyaw > 120)
1582 targetheadyaw = 120;
1583 if (targetheadyaw < -120)
1584 targetheadyaw = -120;
1587 targetheadpitch = 0;
1589 if (targetheadyaw > 80)
1591 if (targetheadyaw < -80)
1592 targetheadyaw = -80;
1593 if (targetheadpitch > 50)
1594 targetheadpitch = 50;
1595 if (targetheadpitch < -50)
1596 targetheadpitch = -50;
1599 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1600 headyaw = targetheadyaw;
1601 else if (headyaw > targetheadyaw) {
1602 headyaw -= multiplier * lookspeed;
1603 } else if (headyaw < targetheadyaw) {
1604 headyaw += multiplier * lookspeed;
1607 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1608 headpitch = targetheadpitch;
1609 else if (headpitch > targetheadpitch) {
1610 headpitch -= multiplier * lookspeed / 2;
1611 } else if (headpitch < targetheadpitch) {
1612 headpitch += multiplier * lookspeed / 2;
1615 rotatearound = jointPos(neck);
1616 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1620 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1621 facing = DoRotation(facing, headpitch * .4, 0, 0);
1622 facing = DoRotation(facing, 0, headyaw * .4, 0);
1625 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1626 facing = DoRotation(facing, headpitch * .8, 0, 0);
1627 facing = DoRotation(facing, 0, headyaw * .8, 0);
1630 if (animTarget == walkanim) {
1631 facing = DoRotation(facing, headpitch * .6, 0, 0);
1632 facing = DoRotation(facing, 0, headyaw * .6, 0);
1635 skeleton.specialforward[0] = facing;
1636 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1637 for (int i = 0; i < skeleton.num_muscles; i++) {
1638 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1639 skeleton.FindRotationMuscle(i, animTarget);
1646 * ragdolls character?
1648 void Person::RagDoll(bool checkcollision)
1653 if (!skeleton.free) {
1656 if (id == 0 && isFlip())
1663 facing = DoRotation(facing, 0, yaw, 0);
1665 skeleton.freetime = 0;
1667 skeleton.longdead = 0;
1670 skeleton.broken = 0;
1671 skeleton.spinny = 1;
1673 skeleton.freefall = 1;
1675 if (!isnormal(velocity.x)) velocity.x = 0;
1676 if (!isnormal(velocity.y)) velocity.y = 0;
1677 if (!isnormal(velocity.z)) velocity.z = 0;
1678 if (!isnormal(yaw)) yaw = 0;
1679 if (!isnormal(coords.x)) coords = 0;
1680 if (!isnormal(tilt)) tilt = 0;
1681 if (!isnormal(tilt2)) tilt2 = 0;
1683 for (int i = 0; i < skeleton.num_joints; i++) {
1684 skeleton.joints[i].delay = 0;
1685 skeleton.joints[i].locked = 0;
1686 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1687 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1688 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1689 skeleton.joints[i].position.y += .1;
1690 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1691 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1694 for (int i = 0; i < skeleton.num_joints; i++) {
1695 skeleton.joints[i].velocity = 0;
1696 skeleton.joints[i].velchange = 0;
1698 skeleton.DoConstraints(&coords, &scale);
1699 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1700 skeleton.DoConstraints(&coords, &scale);
1701 skeleton.DoConstraints(&coords, &scale);
1702 skeleton.DoConstraints(&coords, &scale);
1703 skeleton.DoConstraints(&coords, &scale);
1706 speed = animation[animTarget].speed[frameTarget] * 2;
1707 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1708 speed = animation[animCurrent].speed[frameCurrent] * 2;
1711 speed = transspeed * 2;
1715 for (int i = 0; i < skeleton.num_joints; i++) {
1716 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1717 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((animation[animTarget].position[i][frameTarget] - animation[animCurrent].position[i][frameCurrent]) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1719 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1720 change.x = (float)(Random() % 100) / 100;
1721 change.y = (float)(Random() % 100) / 100;
1722 change.z = (float)(Random() % 100) / 100;
1723 skeleton.joints[i].velocity += change;
1724 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1726 change.x = (float)(Random() % 100) / 100;
1727 change.y = (float)(Random() % 100) / 100;
1728 change.z = (float)(Random() % 100) / 100;
1729 skeleton.joints[i].velchange += change;
1730 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1733 if (checkcollision) {
1740 for (j = 0; j < skeleton.num_joints; j++) {
1741 average += skeleton.joints[j].position;
1745 coords += average * scale;
1746 for (j = 0; j < skeleton.num_joints; j++) {
1747 skeleton.joints[j].position -= average;
1750 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1751 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1752 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1753 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1754 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1757 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1758 coords.x = lowpoint.x;
1759 coords.z = lowpoint.z;
1768 for (int i = 0; i < skeleton.num_joints; i++) {
1769 velocity += skeleton.joints[i].velocity * scale;
1771 velocity /= skeleton.num_joints;
1774 if (Random() % 2 == 0) {
1775 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1776 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1777 weapons[weaponids[0]].velocity.x += .01;
1780 weaponids[0] = weaponids[num_weapons];
1781 if (weaponstuck == num_weapons)
1785 for (unsigned i = 0; i < Person::players.size(); i++) {
1786 Person::players[i]->wentforweapon = 0;
1791 animTarget = bounceidleanim;
1792 animCurrent = bounceidleanim;
1802 void Person::FootLand(bodyparts whichfoot, float opacity)
1804 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1805 cerr << "FootLand called on wrong bodypart" << endl;
1808 static XYZ terrainlight;
1809 static XYZ footvel, footpoint;
1810 if (opacity >= 1 || skiddelay <= 0) {
1813 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1814 if (distsq(&footpoint, &viewer))
1815 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1816 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1817 footvel = velocity / 5;
1820 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1821 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1822 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1823 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1824 if (environment == snowyenvironment) {
1825 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1827 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1829 } else if (environment == grassyenvironment) {
1830 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1831 } else if (environment == desertenvironment) {
1832 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1834 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1838 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1839 footvel = velocity / 5;
1842 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1843 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1844 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1851 * make a puff effect at a body part (dust effect?)
1853 void Person::Puff(int whichlabel)
1855 static XYZ footvel, footpoint;
1858 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1859 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1863 * I think I added this in an attempt to clean up code
1865 void Person::setAnimation(int animation)
1867 animTarget = animation;
1876 void Person::DoAnimations()
1878 if (!skeleton.free) {
1879 static float oldtarget;
1881 if (isIdle() && animCurrent != getIdle())
1882 normalsupdatedelay = 0;
1884 if (animTarget == tempanim || animCurrent == tempanim) {
1885 animation[tempanim] = tempanimation;
1887 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1893 vel[0] = velocity.x;
1894 vel[1] = velocity.y;
1895 vel[2] = velocity.z;
1898 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1899 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1901 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1903 if (!crouchkeydown && velocity.y >= -15)
1906 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1911 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1913 if (normaldotproduct(targfacing, velocity) >= -.3)
1914 animTarget = flipanim;
1916 animTarget = backflipanim;
1917 crouchtogglekeydown = 1;
1925 if (animation[animTarget].attack != reversed)
1927 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1928 crouchtogglekeydown = 0;
1929 if (aitype == playercontrolled)
1932 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1935 crouchtogglekeydown = 1;
1939 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1941 normalsupdatedelay = 0;
1945 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1947 emit_sound_at(fireendsound, coords);
1948 pause_sound(stream_firesound);
1952 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1953 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1955 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1956 if (normaldotproduct(victim->facing, facing) > 0)
1957 victim->animTarget = rabbittackledbackanim;
1959 victim->animTarget = rabbittackledfrontanim;
1960 victim->frameTarget = 2;
1963 victim->targetyaw = yaw;
1964 if (victim->aitype == gethelptype)
1965 victim->DoDamage(victim->damagetolerance - victim->damage);
1966 //victim->DoDamage(30);
1967 if (creature == wolftype) {
1969 emit_sound_at(clawslicesound, victim->coords);
1971 victim->DoBloodBig(1 / victim->armorhead, 210);
1973 award_bonus(id, TackleBonus,
1974 victim->aitype == gethelptype ? 50 : 0);
1978 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1979 if (weapons[weaponids[0]].getType() == knife) {
1980 if (weaponactive == -1)
1982 else if (weaponactive == 0)
1985 if (weaponactive == -1) {
1986 emit_sound_at(knifesheathesound, coords);
1988 if (weaponactive != -1) {
1989 emit_sound_at(knifedrawsound, coords, 128);
1992 drawtogglekeydown = 1;
1995 if (tutoriallevel != 1 || id == 0)
1996 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1999 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2000 if (animation[animTarget].label[frameTarget] == 1)
2001 whichsound = footstepsound;
2003 whichsound = footstepsound2;
2004 if (animation[animTarget].label[frameTarget] == 1)
2005 FootLand(leftfoot, 1);
2006 if (animation[animTarget].label[frameTarget] == 2)
2007 FootLand(rightfoot, 1);
2008 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
2009 FootLand(rightfoot, 1);
2010 FootLand(leftfoot, 1);
2014 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2015 if (animation[animTarget].label[frameTarget] == 1)
2016 whichsound = footstepsound3;
2018 whichsound = footstepsound4;
2022 if (animation[animTarget].label[frameTarget] == 1)
2023 whichsound = footstepsound3;
2025 whichsound = footstepsound4;
2027 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2028 if (animation[animTarget].attack != neutral) {
2029 unsigned r = abs(Random() % 3);
2031 whichsound = lowwhooshsound;
2033 whichsound = midwhooshsound;
2035 whichsound = highwhooshsound;
2037 if (animation[animTarget].attack == neutral)
2038 whichsound = movewhooshsound;
2039 } else if (animation[animTarget].label[frameTarget] == 4)
2040 whichsound = knifeswishsound;
2041 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
2042 whichsound = landsound2;
2044 emit_sound_at(whichsound, coords, 256.);
2047 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2048 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2049 addEnvSound(coords, 15);
2051 addEnvSound(coords, 6);
2055 if (animation[animTarget].label[frameTarget] == 3) {
2057 emit_sound_at(whichsound, coords, 128.);
2062 if (tutoriallevel != 1 || id == 0)
2063 if (speechdelay <= 0)
2064 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2065 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2066 int whichsound = -1;
2067 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2068 if (animation[animTarget].attack != neutral) {
2069 unsigned r = abs(Random() % 4);
2070 if (creature == rabbittype) {
2071 if (r == 0) whichsound = rabbitattacksound;
2072 if (r == 1) whichsound = rabbitattack2sound;
2073 if (r == 2) whichsound = rabbitattack3sound;
2074 if (r == 3) whichsound = rabbitattack4sound;
2076 if (creature == wolftype) {
2077 if (r == 0) whichsound = barksound;
2078 if (r == 1) whichsound = bark2sound;
2079 if (r == 2) whichsound = bark3sound;
2080 if (r == 3) whichsound = barkgrowlsound;
2086 if (whichsound != -1) {
2087 emit_sound_at(whichsound, coords);
2093 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2094 FootLand(leftfoot, 1);
2095 FootLand(rightfoot, 1);
2099 currentoffset = targetoffset;
2100 frameTarget = frameCurrent;
2101 animCurrent = animTarget;
2104 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2105 for (unsigned i = 0; i < weapons.size(); i++) {
2106 if (weapons[i].owner == -1)
2107 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2108 if (distsq(&coords, &weapons[i].position) >= 1) {
2109 if (weapons[i].getType() != staff) {
2110 emit_sound_at(knifedrawsound, coords, 128.);
2119 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2120 for (unsigned i = 0; i < weapons.size(); i++) {
2121 bool willwork = true;
2122 if (weapons[i].owner != -1)
2123 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2124 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2125 if (Person::players[weapons[i].owner]->num_weapons > 1)
2127 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2128 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2129 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2130 bool fleshstuck = false;
2131 if (weapons[i].owner != -1)
2132 if (victim->weaponstuck != -1) {
2133 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2138 emit_sound_at(fleshstabremovesound, coords, 128.);
2140 if (weapons[i].getType() != staff) {
2141 emit_sound_at(knifedrawsound, coords, 128.);
2144 if (weapons[i].owner != -1) {
2145 victim = Person::players[weapons[i].owner];
2146 if (victim->num_weapons == 1)
2147 victim->num_weapons = 0;
2149 victim->num_weapons = 1;
2151 //victim->weaponactive=-1;
2152 victim->skeleton.longdead = 0;
2153 victim->skeleton.free = 1;
2154 victim->skeleton.broken = 0;
2156 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2157 victim->skeleton.joints[j].velchange = 0;
2158 victim->skeleton.joints[j].locked = 0;
2164 Normalise(&relative);
2165 XYZ footvel, footpoint;
2167 footpoint = weapons[i].position;
2168 if (victim->weaponstuck != -1) {
2169 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2171 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2172 weapons[i].bloody = 2;
2173 weapons[i].blooddrip = 5;
2174 victim->weaponstuck = -1;
2177 if (victim->num_weapons > 0) {
2178 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2179 victim->weaponstuck = 0;
2180 if (victim->weaponids[0] == int(i))
2181 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2184 victim->jointVel(abdomen) += relative * 6;
2185 victim->jointVel(neck) += relative * 6;
2186 victim->jointVel(rightshoulder) += relative * 6;
2187 victim->jointVel(leftshoulder) += relative * 6;
2195 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2196 if (weaponactive == -1)
2198 else if (weaponactive == 0) {
2200 if (num_weapons == 2) {
2202 buffer = weaponids[0];
2203 weaponids[0] = weaponids[1];
2204 weaponids[1] = buffer;
2207 if (weaponactive == -1) {
2208 emit_sound_at(knifesheathesound, coords, 128.);
2210 if (weaponactive != -1) {
2211 emit_sound_at(knifedrawsound, coords, 128.);
2216 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2217 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2218 Normalise(&rotatetarget);
2219 targetyaw = -asin(0 - rotatetarget.x);
2220 targetyaw *= 360 / 6.28;
2221 if (rotatetarget.z < 0)
2222 targetyaw = 180 - targetyaw;
2224 if (animTarget == walljumprightkickanim)
2226 if (animTarget == walljumpleftkickanim)
2232 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2235 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2240 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2241 animTarget = rabbittackleanim;
2243 emit_sound_at(jumpsound, coords);
2251 targetloc = velocity;
2252 Normalise(&targetloc);
2253 targetloc += coords;
2254 for (unsigned i = 0; i < Person::players.size(); i++) {
2256 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2257 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2261 if (closestid != -1)
2262 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2264 victim = Person::players[closestid];
2265 coords = victim->coords;
2266 animCurrent = rabbittacklinganim;
2267 animTarget = rabbittacklinganim;
2271 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2272 rotatetarget = coords - victim->coords;
2273 Normalise(&rotatetarget);
2274 targetyaw = -asin(0 - rotatetarget.x);
2275 targetyaw *= 360 / 6.28;
2276 if (rotatetarget.z < 0)
2277 targetyaw = 180 - targetyaw;
2279 if (animTarget != rabbitrunninganim) {
2280 emit_sound_at(jumpsound, coords, 128.);
2286 float damagemult = 1 * power;
2287 if (creature == wolftype)
2288 damagemult = 2.5 * power;
2290 damagemult /= victim->damagetolerance / 200;
2292 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2293 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2294 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2298 if (Random() % 2 || creature == wolftype) {
2301 if (creature == wolftype)
2304 if (tutoriallevel != 1) {
2305 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2307 if (creature == wolftype) {
2308 emit_sound_at(clawslicesound, victim->coords, 128.);
2310 victim->DoBloodBig(2 / victim->armorhead, 175);
2314 relative = victim->coords - coords;
2316 Normalise(&relative);
2317 relative = DoRotation(relative, 0, -90, 0);
2318 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2319 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2321 victim->jointVel(head) += relative * damagemult * 200;
2323 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2329 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2330 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2334 if (Random() % 2 || creature == wolftype) {
2336 if (creature == wolftype)
2339 emit_sound_at(whooshhitsound, victim->coords);
2340 if (creature == wolftype) {
2341 emit_sound_at(clawslicesound, victim->coords, 128.);
2343 victim->DoBloodBig(2, 175);
2347 relative = victim->coords - coords;
2349 Normalise(&relative);
2351 Normalise(&relative);
2352 relative = DoRotation(relative, 0, 90, 0);
2353 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2354 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2356 victim->jointVel(head) += relative * damagemult * 100;
2358 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2362 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2363 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2369 if (tutoriallevel != 1) {
2370 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2372 if (creature == wolftype) {
2373 emit_sound_at(clawslicesound, victim->coords, 128.);
2375 victim->DoBloodBig(2 / victim->armorhead, 175);
2381 Normalise(&relative);
2382 relative = DoRotation(relative, 0, -90, 0);
2383 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2384 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2386 victim->jointVel(head) += relative * damagemult * 200;
2388 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2390 if (victim->damage > victim->damagetolerance)
2391 award_bonus(id, style);
2397 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2398 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2404 if (tutoriallevel != 1) {
2405 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2407 if (creature == wolftype) {
2408 emit_sound_at(clawslicesound, victim->coords, 128.);
2410 victim->DoBloodBig(2 / victim->armorhead, 175);
2416 Normalise(&relative);
2417 relative = DoRotation(relative, 0, 90, 0);
2418 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2419 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2421 victim->jointVel(head) += relative * damagemult * 200;
2423 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2425 if (victim->damage > victim->damagetolerance)
2426 award_bonus(id, style);
2432 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2433 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2441 emit_sound_at(whooshhitsound, victim->coords);
2444 relative = victim->coords - coords;
2446 Normalise(&relative);
2447 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2448 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2450 victim->jointVel(head) += relative * damagemult * 100;
2452 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2456 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2457 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2461 emit_sound_at(whooshhitsound, victim->coords, 128.);
2463 victim->skeleton.longdead = 0;
2464 victim->skeleton.free = 1;
2465 victim->skeleton.broken = 0;
2466 victim->skeleton.spinny = 1;
2468 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2469 victim->skeleton.joints[i].velchange = 0;
2470 victim->skeleton.joints[i].delay = 0;
2471 victim->skeleton.joints[i].locked = 0;
2472 //victim->skeleton.joints[i].velocity=0;
2478 Normalise(&relative);
2479 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2480 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2481 victim->skeleton.joints[i].position.y += relative.y * .3;
2482 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2483 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2485 victim->Puff(abdomen);
2486 victim->jointVel(abdomen).y = relative.y * 400;
2490 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2491 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2495 if (tutoriallevel != 1) {
2496 emit_sound_at(heavyimpactsound, coords, 128.);
2499 relative = victim->coords - coords;
2501 Normalise(&relative);
2502 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2503 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2505 victim->Puff(abdomen);
2506 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2510 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2511 victim->jointVel(abdomen) += relative * damagemult * 300;
2515 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2516 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2520 if (tutoriallevel != 1) {
2521 emit_sound_at(thudsound, coords);
2524 victim->skeleton.longdead = 0;
2525 victim->skeleton.free = 1;
2526 victim->skeleton.broken = 0;
2527 victim->skeleton.spinny = 1;
2529 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2530 victim->skeleton.joints[i].velchange = 0;
2531 //victim->skeleton.joints[i].delay=0;
2532 victim->skeleton.joints[i].locked = 0;
2535 relative = victim->coords - coords;
2536 Normalise(&relative);
2538 Normalise(&relative);
2539 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2540 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2545 victim->Puff(abdomen);
2546 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2547 victim->jointVel(abdomen) += relative * damagemult * 200;
2556 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2559 if (!victim->skeleton.free)
2563 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2564 emit_sound_at(knifesheathesound, coords, 128.);
2567 if (victim && hasvictim) {
2568 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2570 XYZ where, startpoint, endpoint, movepoint, colpoint;
2571 float rotationpoint;
2573 if (weapons[weaponids[weaponactive]].getType() == knife) {
2574 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2575 where -= victim->coords;
2576 if (!victim->skeleton.free)
2577 where = DoRotation(where, 0, -victim->yaw, 0);
2580 startpoint.y += 100;
2584 if (weapons[weaponids[weaponactive]].getType() == sword) {
2585 where = weapons[weaponids[weaponactive]].position;
2586 where -= victim->coords;
2587 if (!victim->skeleton.free)
2588 where = DoRotation(where, 0, -victim->yaw, 0);
2590 where = weapons[weaponids[weaponactive]].tippoint;
2591 where -= victim->coords;
2592 if (!victim->skeleton.free)
2593 where = DoRotation(where, 0, -victim->yaw, 0);
2596 if (weapons[weaponids[weaponactive]].getType() == staff) {
2597 where = weapons[weaponids[weaponactive]].position;
2598 where -= victim->coords;
2599 if (!victim->skeleton.free)
2600 where = DoRotation(where, 0, -victim->yaw, 0);
2602 where = weapons[weaponids[weaponactive]].tippoint;
2603 where -= victim->coords;
2604 if (!victim->skeleton.free)
2605 where = DoRotation(where, 0, -victim->yaw, 0);
2610 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2612 if (whichtri != -1) {
2613 if (victim->dead != 2) {
2614 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2616 award_bonus(id, FinishedBonus);
2619 weapons[weaponids[weaponactive]].bloody = 2;
2621 victim->skeleton.longdead = 0;
2622 victim->skeleton.free = 1;
2623 victim->skeleton.broken = 0;
2625 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2626 victim->skeleton.joints[i].velchange = 0;
2627 victim->skeleton.joints[i].locked = 0;
2628 //victim->skeleton.joints[i].velocity=0;
2630 emit_sound_at(fleshstabsound, coords, 128);
2633 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2634 weapons[weaponids[weaponactive]].blooddrip += 5;
2635 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2637 if (whichtri == -1) {
2639 emit_sound_at(knifesheathesound, coords, 128.);
2645 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2647 emit_sound_at(knifedrawsound, coords, 128);
2650 if (victim && hasvictim) {
2651 XYZ footvel, footpoint;
2653 emit_sound_at(fleshstabremovesound, coords, 128.);
2656 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2658 if (weapons[weaponids[weaponactive]].getType() == sword) {
2659 XYZ where, startpoint, endpoint, movepoint;
2660 float rotationpoint;
2663 where = weapons[weaponids[weaponactive]].position;
2664 where -= victim->coords;
2665 if (!victim->skeleton.free)
2666 where = DoRotation(where, 0, -victim->yaw, 0);
2668 where = weapons[weaponids[weaponactive]].tippoint;
2669 where -= victim->coords;
2670 if (!victim->skeleton.free)
2671 where = DoRotation(where, 0, -victim->yaw, 0);
2676 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2677 footpoint += victim->coords;
2679 if (whichtri == -1) {
2680 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2683 if (weapons[weaponids[weaponactive]].getType() == staff) {
2684 XYZ where, startpoint, endpoint, movepoint;
2685 float rotationpoint;
2688 where = weapons[weaponids[weaponactive]].position;
2689 where -= victim->coords;
2690 if (!victim->skeleton.free)
2691 where = DoRotation(where, 0, -victim->yaw, 0);
2693 where = weapons[weaponids[weaponactive]].tippoint;
2694 where -= victim->coords;
2695 if (!victim->skeleton.free)
2696 where = DoRotation(where, 0, -victim->yaw, 0);
2701 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2702 footpoint += victim->coords;
2704 if (whichtri == -1) {
2705 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2708 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2710 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2711 victim->skeleton.longdead = 0;
2712 victim->skeleton.free = 1;
2713 victim->skeleton.broken = 0;
2715 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2716 victim->skeleton.joints[i].velchange = 0;
2717 victim->skeleton.joints[i].locked = 0;
2718 //victim->skeleton.joints[i].velocity=0;
2724 Normalise(&relative);
2725 //victim->Puff(abdomen);
2727 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2729 if (victim->bloodloss < victim->damagetolerance) {
2730 victim->bloodloss += 1000;
2734 victim->jointVel(abdomen) += relative * damagemult * 20;
2738 if (!hasvictim && onterrain) {
2739 weapons[weaponids[weaponactive]].bloody = 0;
2740 weapons[weaponids[weaponactive]].blooddrip = 0;
2744 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2745 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2753 if (tutoriallevel != 1) {
2754 emit_sound_at(heavyimpactsound, victim->coords, 128);
2759 relative = victim->coords - coords;
2761 Normalise(&relative);
2762 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2763 victim->skeleton.joints[i].velocity = relative * 30;
2765 victim->jointVel(head) += relative * damagemult * 150;
2767 victim->frameTarget = 0;
2768 victim->animTarget = staggerbackhardanim;
2769 victim->targetyaw = targetyaw + 180;
2771 victim->stunned = 1;
2774 victim->Puff(abdomen);
2775 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2782 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2783 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2787 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2788 if (tutoriallevel != 1) {
2789 emit_sound_at(thudsound, victim->coords);
2791 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2792 if (tutoriallevel != 1) {
2793 emit_sound_at(whooshhitsound, victim->coords);
2796 if (tutoriallevel != 1) {
2797 emit_sound_at(heavyimpactsound, victim->coords);
2801 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2804 relative = victim->coords - coords;
2806 Normalise(&relative);
2808 Normalise(&relative);
2809 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2810 victim->skeleton.joints[i].velocity = relative * 5;
2812 victim->jointVel(abdomen) += relative * damagemult * 400;
2814 victim->frameTarget = 0;
2815 victim->animTarget = staggerbackhardanim;
2816 victim->targetyaw = targetyaw + 180;
2818 victim->stunned = 1;
2820 victim->Puff(abdomen);
2821 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2827 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2828 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2829 if (victim->id == 0)
2831 emit_sound_at(landsound2, victim->coords);
2837 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2838 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2839 if (victim->id == 0)
2842 if (weaponactive != -1) {
2843 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2844 if (weapons[victim->weaponids[0]].getType() == staff)
2845 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2846 if (weapons[weaponids[0]].getType() == staff)
2847 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2849 emit_sound_at(swordstaffsound, victim->coords);
2851 emit_sound_at(metalhitsound, victim->coords);
2859 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2860 if (weaponactive != -1) {
2863 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);
2865 weapons[weaponids[0]].thrown(aim * 50);
2868 weaponids[0] = weaponids[num_weapons];
2874 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2876 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2878 if (tutoriallevel != 1)
2879 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2881 award_bonus(id, Slicebonus);
2882 if (tutoriallevel != 1) {
2883 emit_sound_at(knifeslicesound, victim->coords);
2885 //victim->jointVel(abdomen)+=relative*damagemult*200;
2886 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2887 if (victim->id != 0 || difficulty == 2) {
2888 victim->frameTarget = 0;
2889 victim->animTarget = staggerbackhardanim;
2890 victim->targetyaw = targetyaw + 180;
2894 victim->lowreversaldelay = 0;
2895 victim->highreversaldelay = 0;
2896 if (aitype != playercontrolled)
2897 weaponmissdelay = .6;
2899 if (tutoriallevel != 1)
2900 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2901 weapons[weaponids[weaponactive]].bloody = 1;
2902 if (tutoriallevel != 1)
2903 weapons[weaponids[weaponactive]].blooddrip += 3;
2905 XYZ footvel, footpoint;
2907 if (skeleton.free) {
2908 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2910 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2912 if (tutoriallevel != 1) {
2914 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2915 footvel = DoRotation(facing, 0, 90, 0) * .8;
2917 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2918 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2919 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2920 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2922 if (tutoriallevel == 1) {
2923 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2925 victim->DoDamage(damagemult * 0);
2928 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2929 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2930 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2931 award_bonus(id, Slashbonus);
2933 if (tutoriallevel != 1) {
2934 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2935 victim->DoBloodBig(2 / victim->armorhigh, 190);
2937 victim->DoBloodBig(2 / victim->armorhigh, 185);
2938 victim->deathbleeding = 1;
2939 emit_sound_at(swordslicesound, victim->coords);
2941 //victim->jointVel(abdomen)+=relative*damagemult*200;
2942 if (tutoriallevel != 1) {
2943 victim->frameTarget = 0;
2944 victim->animTarget = staggerbackhardanim;
2945 victim->targetyaw = targetyaw + 180;
2949 if (tutoriallevel != 1) {
2950 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2951 weapons[weaponids[weaponactive]].bloody = 1;
2952 weapons[weaponids[weaponactive]].blooddrip += 3;
2954 float bloodlossamount;
2955 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2956 victim->bloodloss += bloodlossamount / victim->armorhigh;
2957 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2958 victim->DoDamage(damagemult * 0);
2960 XYZ footvel, footpoint;
2962 if (skeleton.free) {
2963 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2965 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2968 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2969 footvel = DoRotation(facing, 0, 90, 0) * .8;
2971 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2972 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2973 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2974 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2977 if (victim->weaponactive != -1) {
2978 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2979 if (weapons[victim->weaponids[0]].getType() == staff)
2980 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2981 if (weapons[weaponids[0]].getType() == staff)
2982 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2984 emit_sound_at(swordstaffsound, victim->coords);
2986 emit_sound_at(metalhitsound, victim->coords);
2992 victim->Puff(righthand);
2994 victim->frameTarget = 0;
2995 victim->animTarget = staggerbackhighanim;
2996 victim->targetyaw = targetyaw + 180;
2998 aim = DoRotation(facing, 0, 90, 0) * 21;
3000 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3001 victim->num_weapons--;
3002 if (victim->num_weapons) {
3003 victim->weaponids[0] = victim->weaponids[num_weapons];
3004 if (victim->weaponstuck == victim->num_weapons)
3005 victim->weaponstuck = 0;
3007 victim->weaponactive = -1;
3008 for (unsigned i = 0; i < Person::players.size(); i++) {
3009 Person::players[i]->wentforweapon = 0;
3016 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3017 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3018 if (tutoriallevel != 1) {
3019 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3023 if (Random() % 2 || creature == wolftype) {
3026 emit_sound_at(staffheadsound, victim->coords);
3030 relative = victim->coords - coords;
3032 Normalise(&relative);
3033 relative = DoRotation(relative, 0, 90, 0);
3035 Normalise(&relative);
3036 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3037 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3039 victim->jointVel(head) += relative * damagemult * 230;
3040 victim->jointVel(neck) += relative * damagemult * 230;
3042 if (tutoriallevel != 1) {
3043 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3045 award_bonus(id, solidhit, 30);
3050 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3051 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3052 if (tutoriallevel != 1) {
3053 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3057 if (Random() % 2 || creature == wolftype) {
3060 emit_sound_at(staffheadsound, victim->coords);
3064 relative = victim->coords - coords;
3066 Normalise(&relative);
3067 relative = DoRotation(relative, 0, -90, 0);
3068 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3069 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3071 victim->jointVel(head) += relative * damagemult * 220;
3072 victim->jointVel(neck) += relative * damagemult * 220;
3074 if (tutoriallevel != 1) {
3075 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3077 award_bonus(id, solidhit, 60);
3082 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3083 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3085 if (tutoriallevel != 1) {
3087 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3090 if (Random() % 2 || creature == wolftype) {
3093 emit_sound_at(staffbodysound, victim->coords);
3095 victim->skeleton.longdead = 0;
3096 victim->skeleton.free = 1;
3097 victim->skeleton.broken = 0;
3099 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3100 victim->skeleton.joints[i].velchange = 0;
3101 victim->skeleton.joints[i].locked = 0;
3102 //victim->skeleton.joints[i].velocity=0;
3109 Normalise(&relative);
3110 if (!victim->dead) {
3111 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3112 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3114 victim->jointVel(abdomen) += relative * damagemult * 40;
3117 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3118 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3121 victim->Puff(abdomen);
3122 if (tutoriallevel != 1) {
3123 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3125 if (!victim->dead) {
3126 award_bonus(id, solidhit, 40);
3132 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3133 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3138 relative = victim->coords - coords;
3140 Normalise(&relative);
3144 if (animation[victim->animTarget].height == lowheight) {
3150 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3151 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3153 victim->jointVel(head) += relative * damagemult * 200;
3154 if (tutoriallevel != 1) {
3155 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3158 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3159 if (victim->howactive == typesleeping)
3160 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3161 if (creature == wolftype) {
3162 emit_sound_at(clawslicesound, victim->coords, 128.);
3164 victim->DoBloodBig(2 / victim->armorhead, 175);
3167 if (victim->damage >= victim->damagetolerance)
3169 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3170 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3172 victim->jointVel(abdomen) += relative * damagemult * 200;
3173 victim->frameTarget = 0;
3174 victim->animTarget = staggerbackhighanim;
3175 victim->targetyaw = targetyaw + 180;
3177 if (tutoriallevel != 1) {
3178 emit_sound_at(landsound2, victim->coords, 128.);
3180 victim->Puff(abdomen);
3181 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3182 if (creature == wolftype) {
3183 emit_sound_at(clawslicesound, victim->coords, 128.);
3185 victim->DoBloodBig(2 / victim->armorhigh, 170);
3192 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3193 if ((victim->animTarget != jumpupanim) &&
3194 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3195 (victim != this->shared_from_this())) {
3199 if (tutoriallevel != 1) {
3200 emit_sound_at(landsound2, victim->coords, 128.);
3203 relative = victim->coords - coords;
3205 Normalise(&relative);
3207 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3210 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3211 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3213 relative = DoRotation(relative, 0, -90, 0);
3215 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3216 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)
3217 victim->skeleton.joints[i].velocity = relative * 80;
3219 victim->Puff(rightankle);
3220 victim->Puff(leftankle);
3221 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3223 if (victim->damage >= victim->damagetolerance)
3225 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3226 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3228 relative = DoRotation(relative, 0, -90, 0);
3229 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3230 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)
3231 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3233 victim->jointVel(abdomen) += relative * damagemult * 200;
3234 victim->frameTarget = 0;
3235 victim->animTarget = staggerbackhighanim;
3236 victim->targetyaw = targetyaw + 180;
3238 if (tutoriallevel != 1) {
3239 emit_sound_at(landsound2, victim->coords, 128.);
3241 victim->Puff(abdomen);
3242 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3250 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3251 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3259 if (tutoriallevel != 1) {
3260 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3262 if (creature == wolftype) {
3263 emit_sound_at(clawslicesound, victim->coords, 128);
3265 victim->DoBloodBig(2 / victim->armorhigh, 170);
3269 relative = victim->coords - oldcoords;
3271 Normalise(&relative);
3272 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3273 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3275 victim->jointVel(abdomen) += relative * damagemult * 200;
3276 victim->Puff(abdomen);
3277 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3279 award_bonus(id, Reversal);
3282 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3283 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3284 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3285 takeWeapon(victim->weaponids[victim->weaponactive]);
3286 victim->num_weapons--;
3287 if (victim->num_weapons > 0) {
3288 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3290 victim->weaponactive = -1;
3295 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3303 emit_sound_at(whooshhitsound, victim->coords, 128.);
3306 relative = victim->coords - oldcoords;
3308 Normalise(&relative);
3309 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3310 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3312 victim->jointVel(abdomen) += relative * damagemult * 200;
3314 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3317 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3326 award_bonus(id, staffreversebonus);
3328 if (tutoriallevel != 1) {
3329 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3332 award_bonus(id, staffreversebonus); // Huh, again?
3335 relative = victim->coords - oldcoords;
3337 Normalise(&relative);
3338 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3339 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3341 victim->jointVel(abdomen) += relative * damagemult * 200;
3343 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3346 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3352 Normalise(&relative);
3354 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3355 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3357 victim->jointVel(lefthand) *= .1;
3358 victim->jointVel(leftwrist) *= .2;
3359 victim->jointVel(leftelbow) *= .5;
3360 victim->jointVel(leftshoulder) *= .7;
3361 victim->jointVel(righthand) *= .1;
3362 victim->jointVel(rightwrist) *= .2;
3363 victim->jointVel(rightelbow) *= .5;
3364 victim->jointVel(rightshoulder) *= .7;
3366 victim->Puff(abdomen);
3367 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3369 award_bonus(id, Reversal);
3373 if (weaponactive != -1 || creature == wolftype)
3375 if (creature == rabbittype && weaponactive != -1)
3376 if (weapons[weaponids[0]].getType() == staff)
3379 if (weaponactive != -1) {
3380 victim->DoBloodBig(2 / victim->armorhigh, 225);
3381 emit_sound_at(knifeslicesound, victim->coords);
3382 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3383 weapons[weaponids[weaponactive]].bloody = 1;
3384 weapons[weaponids[weaponactive]].blooddrip += 3;
3386 if (weaponactive == -1 && creature == wolftype) {
3387 emit_sound_at(clawslicesound, victim->coords, 128.);
3389 victim->DoBloodBig(2 / victim->armorhigh, 175);
3396 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3402 Normalise(&relative);
3404 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3405 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3407 victim->jointVel(lefthand) *= .1 - 1;
3408 victim->jointVel(leftwrist) *= .2 - 1;
3409 victim->jointVel(leftelbow) *= .5 - 1;
3410 victim->jointVel(leftshoulder) *= .7 - 1;
3411 victim->jointVel(righthand) *= .1 - 1;
3412 victim->jointVel(rightwrist) *= .2 - 1;
3413 victim->jointVel(rightelbow) *= .5 - 1;
3414 victim->jointVel(rightshoulder) *= .7 - 1;
3416 award_bonus(id, swordreversebonus);
3419 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3427 if (tutoriallevel != 1) {
3428 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3432 relative = victim->coords - oldcoords;
3434 Normalise(&relative);
3435 relative = DoRotation(relative, 0, -90, 0);
3436 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3437 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3439 victim->jointVel(abdomen) += relative * damagemult * 200;
3440 victim->Puff(abdomen);
3441 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3443 award_bonus(id, Reversal);
3446 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3449 victim->skeleton.spinny = 0;
3451 relative = facing * -1;
3453 Normalise(&relative);
3454 if (victim->id == 0)
3456 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3457 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3459 victim->damage = victim->damagetolerance;
3460 victim->permanentdamage = victim->damagetolerance - 1;
3463 if (weaponactive != -1 || creature == wolftype)
3465 if (creature == rabbittype && weaponactive != -1)
3466 if (weapons[weaponids[0]].getType() == staff)
3469 if (weaponactive != -1) {
3470 victim->DoBloodBig(200, 225);
3471 emit_sound_at(knifeslicesound, victim->coords);
3473 weapons[weaponids[weaponactive]].bloody = 2;
3474 weapons[weaponids[weaponactive]].blooddrip += 5;
3477 if (creature == wolftype && weaponactive == -1) {
3478 emit_sound_at(clawslicesound, victim->coords, 128.);
3480 victim->DoBloodBig(2, 175);
3483 award_bonus(id, spinecrusher);
3486 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3487 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3489 if (animTarget == knifefollowanim)
3490 victim->DoBloodBig(200, 210);
3491 if (animTarget == knifesneakattackanim) {
3492 XYZ footvel, footpoint;
3494 footpoint = weapons[weaponids[0]].tippoint;
3496 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3497 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3498 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3499 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3500 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3501 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3502 victim->DoBloodBig(200, 195);
3503 award_bonus(id, tracheotomy);
3505 if (animTarget == knifefollowanim) {
3506 award_bonus(id, Stabbonus);
3507 XYZ footvel, footpoint;
3509 footpoint = weapons[weaponids[0]].tippoint;
3511 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3512 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3513 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3514 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3515 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3516 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3519 victim->bloodloss += 10000;
3520 victim->velocity = 0;
3521 emit_sound_at(fleshstabsound, victim->coords);
3523 weapons[weaponids[weaponactive]].bloody = 2;
3524 weapons[weaponids[weaponactive]].blooddrip += 5;
3528 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3530 victim->velocity = 0;
3531 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3532 victim->skeleton.joints[i].velocity = 0;
3534 if (animTarget == knifefollowanim) {
3536 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3537 victim->skeleton.joints[i].velocity = 0;
3540 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3541 emit_sound_at(fleshstabremovesound, victim->coords);
3543 weapons[weaponids[weaponactive]].bloody = 2;
3544 weapons[weaponids[weaponactive]].blooddrip += 5;
3546 XYZ footvel, footpoint;
3548 footpoint = weapons[weaponids[0]].tippoint;
3550 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3551 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3552 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3553 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3554 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3555 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3559 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3560 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3561 award_bonus(id, backstab);
3565 XYZ footvel, footpoint;
3567 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3569 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3570 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3571 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3572 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3573 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3574 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3575 victim->DoBloodBig(200, 180);
3576 victim->DoBloodBig(200, 215);
3577 victim->bloodloss += 10000;
3578 victim->velocity = 0;
3579 emit_sound_at(fleshstabsound, victim->coords);
3581 weapons[weaponids[weaponactive]].bloody = 2;
3582 weapons[weaponids[weaponactive]].blooddrip += 5;
3586 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3588 victim->velocity = 0;
3589 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3590 victim->skeleton.joints[i].velocity = 0;
3592 if (weaponactive != -1) {
3593 emit_sound_at(fleshstabremovesound, victim->coords);
3595 weapons[weaponids[weaponactive]].bloody = 2;
3596 weapons[weaponids[weaponactive]].blooddrip += 5;
3598 XYZ footvel, footpoint;
3600 footpoint = weapons[weaponids[0]].tippoint;
3602 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3603 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3604 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3605 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3606 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3607 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3611 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3619 if (weaponactive == -1) {
3620 if (tutoriallevel != 1) {
3621 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3626 if (weaponactive != -1 || creature == wolftype)
3628 if (creature == rabbittype && weaponactive != -1)
3629 if (weapons[weaponids[0]].getType() == staff)
3632 if (weaponactive != -1) {
3633 victim->DoBloodBig(2 / victim->armorhead, 225);
3634 emit_sound_at(knifeslicesound, victim->coords);
3635 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3636 weapons[weaponids[weaponactive]].bloody = 1;
3637 weapons[weaponids[weaponactive]].blooddrip += 3;
3639 if (weaponactive == -1 && creature == wolftype) {
3640 emit_sound_at(clawslicesound, victim->coords, 128.);
3642 victim->DoBloodBig(2 / victim->armorhead, 175);
3646 award_bonus(id, Reversal);
3651 relative = facing * -1;
3653 Normalise(&relative);
3654 relative = DoRotation(relative, 0, 90, 0);
3656 Normalise(&relative);
3657 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3658 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3660 victim->jointVel(head) += relative * damagemult * 200;
3661 if (victim->damage < victim->damagetolerance - 100)
3662 victim->velocity = relative * 200;
3663 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3664 victim->velocity = 0;
3667 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3671 relative = facing * -1;
3673 Normalise(&relative);
3674 relative = DoRotation(relative, 0, 90, 0);
3676 Normalise(&relative);
3677 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3678 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3680 victim->jointVel(head) += relative * damagemult * 200;
3683 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3684 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3685 award_bonus(id, reverseko);
3691 if (frameTarget > animation[animCurrent].numframes - 1) {
3694 animTarget = getIdle();
3695 FootLand(leftfoot, 1);
3696 FootLand(rightfoot, 1);
3698 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3699 animTarget = rollanim;
3701 emit_sound_at(movewhooshsound, coords, 128.);
3703 if (animCurrent == staggerbackhighanim) {
3704 animTarget = getIdle();
3706 if (animCurrent == staggerbackhardanim) {
3707 animTarget = getIdle();
3709 if (animCurrent == removeknifeanim) {
3710 animTarget = getIdle();
3712 if (animCurrent == crouchremoveknifeanim) {
3713 animTarget = getCrouch();
3715 if (animCurrent == backhandspringanim) {
3716 animTarget = getIdle();
3718 if (animCurrent == dodgebackanim) {
3719 animTarget = getIdle();
3721 if (animCurrent == drawleftanim) {
3722 animTarget = getIdle();
3724 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3725 animTarget = getIdle();
3726 if (animCurrent == crouchdrawrightanim) {
3727 animTarget = getCrouch();
3729 if (weaponactive == -1)
3731 else if (weaponactive == 0) {
3733 if (num_weapons == 2) {
3735 buffer = weaponids[0];
3736 weaponids[0] = weaponids[1];
3737 weaponids[1] = buffer;
3741 if (weaponactive == -1) {
3742 emit_sound_at(knifesheathesound, coords, 128.);
3744 if (weaponactive != -1) {
3745 emit_sound_at(knifedrawsound, coords, 128.);
3748 if (animCurrent == rollanim) {
3749 animTarget = getCrouch();
3750 FootLand(leftfoot, 1);
3751 FootLand(rightfoot, 1);
3754 if (animTarget == walljumprightkickanim) {
3757 if (animTarget == walljumpleftkickanim) {
3760 animTarget = jumpdownanim;
3762 if (animCurrent == climbanim) {
3763 animTarget = getCrouch();
3765 coords += facing * .1;
3766 if (!isnormal(coords.x))
3777 if (animTarget == rabbitkickreversalanim) {
3778 animTarget = getCrouch();
3781 if (animTarget == jumpreversalanim) {
3782 animTarget = getCrouch();
3785 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3786 if (attackkeydown && animTarget != walljumpfrontanim) {
3788 float closestdist = -1;
3790 if (Person::players.size() > 1)
3791 for (unsigned i = 0; i < Person::players.size(); i++) {
3792 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3793 distance = distsq(&Person::players[i]->coords, &coords);
3794 if (closestdist == -1 || distance < closestdist) {
3795 closestdist = distance;
3800 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3801 victim = Person::players[closest];
3802 animTarget = walljumprightkickanim;
3804 XYZ rotatetarget = victim->coords - coords;
3805 Normalise(&rotatetarget);
3806 yaw = -asin(0 - rotatetarget.x);
3808 if (rotatetarget.z < 0)
3810 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3811 velocity = (victim->coords - coords) * 4;
3816 if (animTarget == walljumpbackanim) {
3817 animTarget = backflipanim;
3819 velocity = facing * -8;
3822 resume_stream(whooshsound);
3824 if (animTarget == walljumprightanim) {
3825 animTarget = rightflipanim;
3829 velocity = DoRotation(facing, 0, 30, 0) * -8;
3832 if (animTarget == walljumpfrontanim) {
3833 animTarget = frontflipanim;
3837 velocity = facing * 8;
3841 resume_stream(whooshsound);
3843 if (animTarget == walljumpleftanim) {
3844 if (attackkeydown) {
3846 float closestdist = -1;
3848 if (Person::players.size() > 1)
3849 for (unsigned i = 0; i < Person::players.size(); i++) {
3850 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3851 distance = distsq(&Person::players[i]->coords, &coords);
3852 if (closestdist == -1 || distance < closestdist) {
3853 closestdist = distance;
3858 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3859 victim = Person::players[closest];
3860 animTarget = walljumpleftkickanim;
3862 XYZ rotatetarget = victim->coords - coords;
3863 Normalise(&rotatetarget);
3864 yaw = -asin(0 - rotatetarget.x);
3866 if (rotatetarget.z < 0)
3868 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3869 velocity = (victim->coords - coords) * 4;
3874 if (animTarget != walljumpleftkickanim) {
3875 animTarget = leftflipanim;
3879 velocity = DoRotation(facing, 0, -30, 0) * -8;
3883 resume_stream(whooshsound);
3885 if (animTarget == sneakattackanim) {
3886 animCurrent = getCrouch();
3887 animTarget = getCrouch();
3894 transspeed = 1000000;
3895 targetheadyaw += 180;
3896 coords -= facing * .7;
3898 coords.y = terrain.getHeight(coords.x, coords.z);
3902 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3903 animTarget = getIdle();
3906 coords.y = terrain.getHeight(coords.x, coords.z);
3910 if (animCurrent == knifefollowanim) {
3911 animTarget = getIdle();
3914 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3915 float ycoords = oldcoords.y;
3916 animTarget = getStop();
3921 transspeed = 1000000;
3922 targetheadyaw += 180;
3923 if (!isnormal(coords.x))
3925 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3926 oldcoords = coords + facing * .5;
3927 else if (animCurrent == sweepreversalanim)
3928 oldcoords = coords + facing * 1.1;
3929 else if (animCurrent == upunchreversalanim) {
3930 oldcoords = coords + facing * 1.5;
3933 targetheadyaw += 180;
3936 } else if (animCurrent == knifeslashreversalanim) {
3937 oldcoords = coords + facing * .5;
3940 targetheadyaw += 90;
3943 } else if (animCurrent == staffspinhitreversalanim) {
3946 targetheadyaw += 180;
3951 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3953 oldcoords.y = ycoords;
3954 currentoffset = coords - oldcoords;
3960 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3965 if (animation[animTarget].attack == reversed) {
3967 if (animTarget == sweepreversedanim)
3969 animTarget = backhandspringanim;
3971 emit_sound_at(landsound, coords, 128);
3973 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3974 animTarget = rollanim;
3977 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3978 coords.y = oldcoords.y;
3980 if (animCurrent == knifeslashreversedanim) {
3981 animTarget = rollanim;
3986 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3987 coords.y = oldcoords.y;
3991 animTarget = jumpdownanim;
3994 animTarget = getIdle();
3996 animTarget = getIdle();
3997 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3998 animTarget = getIdle();
4000 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4001 coords.y = oldcoords.y;
4002 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
4003 targetoffset.y = coords.y;
4005 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4006 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
4007 currentoffset.y -= (coords.y - targetoffset.y);
4008 coords.y = targetoffset.y;
4010 normalsupdatedelay = 0;
4012 if (animCurrent == upunchanim) {
4013 animTarget = getStop();
4014 normalsupdatedelay = 0;
4017 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4021 if (num_weapons > 0)
4022 if (weapons[0].getType() == staff)
4028 rabbitkickragdoll = 1;
4030 if (animCurrent == rabbitkickreversedanim) {
4036 skeleton.spinny = 0;
4037 SolidHitBonus(!id); // FIXME: tricky id
4041 animTarget = rollanim;
4044 pause_sound(whooshsound);
4048 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4052 skeleton.spinny = 0;
4054 if (animCurrent == jumpreversedanim) {
4060 skeleton.spinny = 0;
4061 SolidHitBonus(!id); // FIXME: tricky id
4065 animTarget = rollanim;
4066 coords += facing * 2;
4068 pause_sound(whooshsound);
4073 if (animation[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
4074 animTarget = getupfromfrontanim;
4076 } else if (animation[animCurrent].attack == normalattack) {
4077 animTarget = getIdle();
4080 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4081 animTarget = blockhighleftstrikeanim;
4083 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4084 animTarget = getIdle();
4087 if (animCurrent == spinkickanim && victim->skeleton.free) {
4088 if (creature == rabbittype)
4089 animTarget = fightidleanim;
4094 if (isIdle() && !wasIdle())
4095 normalsupdatedelay = 0;
4097 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4098 animTarget = jumpdownanim;
4101 if (!skeleton.free) {
4103 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4104 if (!isRun() || !wasRun()) {
4105 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4106 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4107 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4108 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4110 if (isRun() && wasRun()) {
4112 tempspeed = velspeed;
4113 if (tempspeed < 10 * speedmult)
4114 tempspeed = 10 * speedmult;
4115 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4117 } else if (transspeed)
4118 target += multiplier * transspeed * speed * 2;
4120 if (!isRun() || !wasRun()) {
4121 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4122 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4123 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4124 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4128 if (animCurrent != animTarget)
4129 target = (target + oldtarget) / 2;
4132 frameCurrent = frameTarget;
4136 rot = targetrot * target;
4137 yaw += rot - oldrot;
4143 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4145 for (int i = 0; i < skeleton.num_joints; i++) {
4146 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4149 skeleton.FindForwards();
4151 for (int i = 0; i < skeleton.num_muscles; i++) {
4152 if (skeleton.muscles[i].visible) {
4153 skeleton.FindRotationMuscle(i, animTarget);
4156 for (int i = 0; i < skeleton.num_muscles; i++) {
4157 if (skeleton.muscles[i].visible) {
4158 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4159 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4160 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4161 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4162 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4163 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4168 for (int i = 0; i < skeleton.num_joints; i++) {
4169 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4172 skeleton.FindForwards();
4174 for (int i = 0; i < skeleton.num_muscles; i++) {
4175 if (skeleton.muscles[i].visible) {
4176 skeleton.FindRotationMuscle(i, animTarget);
4179 for (int i = 0; i < skeleton.num_muscles; i++) {
4180 if (skeleton.muscles[i].visible) {
4181 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4182 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4183 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4184 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4185 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4186 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4187 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4188 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4189 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4190 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4191 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4192 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4196 if (frameCurrent >= animation[animCurrent].numframes)
4197 frameCurrent = animation[animCurrent].numframes - 1;
4199 oldanimCurrent = animCurrent;
4200 oldanimTarget = animTarget;
4201 oldframeTarget = frameTarget;
4202 oldframeCurrent = frameCurrent;
4204 for (int i = 0; i < skeleton.num_joints; i++) {
4205 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4206 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4208 offset = currentoffset * (1 - target) + targetoffset * target;
4209 for (int i = 0; i < skeleton.num_muscles; i++) {
4210 if (skeleton.muscles[i].visible) {
4211 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4212 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4213 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4218 if (isLanding() && landhard) {
4221 animTarget = getLandhard();
4234 void Person::DoStuff()
4236 static XYZ terrainnormal;
4237 static XYZ flatfacing;
4238 static XYZ flatvelocity;
4239 static float flatvelspeed;
4243 static int bloodsize;
4244 static int startx, starty, endx, endy;
4245 static GLubyte color;
4246 static XYZ bloodvel;
4248 onfiredelay -= multiplier;
4249 if (onfiredelay < 0 && onfire) {
4250 if (Random() % 2 == 0) {
4256 crouchkeydowntime += multiplier;
4258 crouchkeydowntime = 0;
4259 jumpkeydowntime += multiplier;
4260 if (!jumpkeydown && skeleton.free)
4261 jumpkeydowntime = 0;
4263 if (hostile || damage > 0 || bloodloss > 0)
4266 if (isIdle() || isRun())
4269 if (num_weapons == 1 && weaponactive != -1)
4273 blooddimamount -= multiplier * .3;
4274 speechdelay -= multiplier;
4275 texupdatedelay -= multiplier;
4276 interestdelay -= multiplier;
4277 flamedelay -= multiplier;
4278 parriedrecently -= multiplier;
4280 victim = this->shared_from_this();
4285 speed = 1.1 * speedmult;
4287 speed = 1.0 * speedmult;
4289 rabbitkickragdoll = 0;
4293 if (id != 0 && (creature == rabbittype || difficulty != 2))
4295 if (id != 0 && creature == wolftype && difficulty == 2) {
4297 if (aitype != passivetype) {
4299 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) {
4305 if (animTarget == wolfrunninganim && !superruntoggle) {
4306 animTarget = getRun();
4310 if (weaponactive == -1 && num_weapons > 0) {
4311 if (weapons[weaponids[0]].getType() == staff) {
4317 burnt += multiplier;
4321 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4323 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4329 vel[0] = velocity.x;
4330 vel[1] = velocity.y;
4331 vel[2] = velocity.z;
4334 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4335 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4339 while (flamedelay < 0 && onfire) {
4341 howmany = abs(Random() % (skeleton.num_joints));
4342 if (skeleton.free) {
4343 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4344 flatfacing = skeleton.joints[howmany].position * scale + coords;
4346 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4347 flatvelocity = (coords - oldcoords) / multiplier / 2;
4349 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4352 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4354 howmany = abs(Random() % (skeleton.num_joints));
4355 if (skeleton.free) {
4356 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4357 flatfacing = skeleton.joints[howmany].position * scale + coords;
4359 flatvelocity = (coords - oldcoords) / multiplier / 2;
4360 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4362 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4366 bleeding -= multiplier * .3;
4367 if (bloodtoggle == 2) {
4368 skeleton.drawmodel.textureptr.bind();
4369 if ((bleeding <= 0) && (detail != 2))
4374 if (neckspurtamount > 0) {
4375 neckspurtamount -= multiplier;
4376 neckspurtdelay -= multiplier * 3;
4377 neckspurtparticledelay -= multiplier * 3;
4378 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4381 if (skeleton.free) {
4382 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4383 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4384 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4386 bloodvel.z = 5 * neckspurtamount;
4387 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4388 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4389 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4391 neckspurtparticledelay = .05;
4393 if (neckspurtdelay < 0) {
4398 if (deathbleeding > 0 && dead != 2) {
4399 if (deathbleeding < 5)
4400 bleeddelay -= deathbleeding * multiplier / 4;
4402 bleeddelay -= 5 * multiplier / 4;
4403 if (bleeddelay < 0 && bloodtoggle) {
4408 if (skeleton.free) {
4409 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4410 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4412 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4413 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4417 bloodloss += deathbleeding * multiplier * 80;
4418 deathbleeding -= multiplier * 1.6;
4419 if (deathbleeding < 0)
4421 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4422 if (weaponactive != -1) {
4423 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4424 weapons[weaponids[0]].velocity.x += .01;
4427 weaponids[0] = weaponids[num_weapons];
4428 if (weaponstuck == num_weapons)
4432 for (unsigned i = 0; i < Person::players.size(); i++) {
4433 Person::players[i]->wentforweapon = 0;
4441 if (!dead && creature == wolftype) {
4442 award_bonus(0, Wolfbonus);
4445 if (animTarget == knifefollowedanim && !skeleton.free) {
4446 for (int i = 0; i < skeleton.num_joints; i++) {
4447 skeleton.joints[i].velocity = 0;
4448 skeleton.joints[i].velocity.y = -2;
4451 if (id != 0 && unconscioustime > .1) {
4459 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4460 texupdatedelay = .12;
4462 bloodsize = 5 - realtexdetail;
4466 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4467 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4468 endx = startx + bloodsize;
4469 endy = starty + bloodsize;
4479 if (endx > skeleton.skinsize - 1) {
4480 endx = skeleton.skinsize - 1;
4483 if (endy > skeleton.skinsize - 1) {
4484 endy = skeleton.skinsize - 1;
4492 for (i = startx; i < endx; i++) {
4493 for (j = starty; j < endy; j++) {
4494 if (Random() % 2 == 0) {
4495 color = Random() % 85 + 170;
4496 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4497 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4498 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4499 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4504 skeleton.drawmodel.textureptr.bind();
4508 if (skeleton.free) {
4509 bleedx += 4 * direction / realtexdetail;
4511 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4513 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4515 bleedy -= 4 / realtexdetail;
4517 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4519 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4523 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4524 righthandmorphness = targetrighthandmorphness;
4525 righthandmorphstart = righthandmorphend;
4526 } else if (righthandmorphness > targetrighthandmorphness) {
4527 righthandmorphness -= multiplier * 4;
4528 } else if (righthandmorphness < targetrighthandmorphness) {
4529 righthandmorphness += multiplier * 4;
4532 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4533 lefthandmorphness = targetlefthandmorphness;
4534 lefthandmorphstart = lefthandmorphend;
4535 } else if (lefthandmorphness > targetlefthandmorphness) {
4536 lefthandmorphness -= multiplier * 4;
4537 } else if (lefthandmorphness < targetlefthandmorphness) {
4538 lefthandmorphness += multiplier * 4;
4541 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4542 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4543 tailmorphness = targettailmorphness;
4544 tailmorphstart = tailmorphend;
4545 } else if (tailmorphness > targettailmorphness) {
4546 tailmorphness -= multiplier * 10;
4547 } else if (tailmorphness < targettailmorphness) {
4548 tailmorphness += multiplier * 10;
4552 if (creature == wolftype) {
4553 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4554 tailmorphness = targettailmorphness;
4555 tailmorphstart = tailmorphend;
4556 } else if (tailmorphness > targettailmorphness) {
4557 tailmorphness -= multiplier * 2;
4558 } else if (tailmorphness < targettailmorphness) {
4559 tailmorphness += multiplier * 2;
4563 if (headmorphend == 3 || headmorphstart == 3) {
4564 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4565 headmorphness = targetheadmorphness;
4566 headmorphstart = headmorphend;
4567 } else if (headmorphness > targetheadmorphness) {
4568 headmorphness -= multiplier * 7;
4569 } else if (headmorphness < targetheadmorphness) {
4570 headmorphness += multiplier * 7;
4572 } else if (headmorphend == 5 || headmorphstart == 5) {
4573 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4574 headmorphness = targetheadmorphness;
4575 headmorphstart = headmorphend;
4576 } else if (headmorphness > targetheadmorphness) {
4577 headmorphness -= multiplier * 10;
4578 } else if (headmorphness < targetheadmorphness) {
4579 headmorphness += multiplier * 10;
4582 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4583 headmorphness = targetheadmorphness;
4584 headmorphstart = headmorphend;
4585 } else if (headmorphness > targetheadmorphness) {
4586 headmorphness -= multiplier * 4;
4587 } else if (headmorphness < targetheadmorphness) {
4588 headmorphness += multiplier * 4;
4592 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4593 chestmorphness = targetchestmorphness;
4594 chestmorphstart = chestmorphend;
4595 } else if (chestmorphness > targetchestmorphness) {
4596 chestmorphness -= multiplier;
4597 } else if (chestmorphness < targetchestmorphness) {
4598 chestmorphness += multiplier;
4601 if (dead != 2 && howactive <= typesleeping) {
4602 if (chestmorphstart == 0 && chestmorphend == 0) {
4604 targetchestmorphness = 1;
4607 if (chestmorphstart != 0 && chestmorphend != 0) {
4609 targetchestmorphness = 1;
4611 if (environment == snowyenvironment) {
4614 if (skeleton.free) {
4615 footvel = skeleton.specialforward[0] * -1;
4616 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4618 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4619 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4621 if (animTarget == sleepanim)
4622 footvel = DoRotation(footvel, 0, 90, 0);
4623 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4627 if (!dead && howactive < typesleeping) {
4628 blinkdelay -= multiplier * 2;
4629 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4631 targetheadmorphness = 1;
4633 blinkdelay = (float)(abs(Random() % 40)) / 5;
4635 if (headmorphstart == 3 && headmorphend == 3) {
4637 targetheadmorphness = 1;
4642 twitchdelay -= multiplier * 1.5;
4643 if (animTarget != hurtidleanim) {
4644 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4646 targetheadmorphness = 1;
4648 twitchdelay = (float)(abs(Random() % 40)) / 5;
4650 if (headmorphstart == 5 && headmorphend == 5) {
4652 targetheadmorphness = 1;
4656 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4657 twitchdelay3 -= multiplier * 1;
4658 if (Random() % 2 == 0) {
4659 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4660 righthandmorphness = 0;
4661 targetrighthandmorphness = 1;
4662 righthandmorphend = 1;
4663 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4665 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4666 righthandmorphness = 0;
4667 targetrighthandmorphness = 1;
4668 righthandmorphend = 0;
4671 if (Random() % 2 == 0) {
4672 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4673 lefthandmorphness = 0;
4674 targetlefthandmorphness = 1;
4675 lefthandmorphend = 1;
4676 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4678 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4679 lefthandmorphness = 0;
4680 targetlefthandmorphness = 1;
4681 lefthandmorphend = 0;
4687 if (creature == rabbittype) {
4688 if (howactive < typesleeping)
4689 twitchdelay2 -= multiplier * 1.5;
4691 twitchdelay2 -= multiplier * 0.5;
4692 if (howactive <= typesleeping) {
4693 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4695 targettailmorphness = 1;
4697 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4699 if (tailmorphstart == 1 && tailmorphend == 1) {
4701 targettailmorphness = 1;
4704 if (tailmorphstart == 2 && tailmorphend == 2) {
4706 targettailmorphness = 1;
4713 if (creature == wolftype) {
4714 twitchdelay2 -= multiplier * 1.5;
4715 if (tailmorphend != 0)
4716 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4718 targettailmorphness = 1;
4722 if (tailmorphend != 5)
4723 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4725 targettailmorphness = 1;
4729 if (twitchdelay2 <= 0) {
4730 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4732 targettailmorphness = 1;
4735 if (tailmorphstart == 1 && tailmorphend == 1) {
4737 targettailmorphness = 1;
4740 if (tailmorphstart == 2 && tailmorphend == 2) {
4742 targettailmorphness = 1;
4745 if (tailmorphstart == 3 && tailmorphend == 3) {
4747 targettailmorphness = 1;
4750 if (tailmorphstart == 4 && tailmorphend == 4) {
4752 targettailmorphness = 1;
4759 unconscioustime = 0;
4761 if (dead == 1 || howactive == typesleeping) {
4762 unconscioustime += multiplier;
4763 //If unconscious, close eyes and mouth
4764 if (righthandmorphend != 0)
4765 righthandmorphness = 0;
4766 righthandmorphend = 0;
4767 targetrighthandmorphness = 1;
4769 if (lefthandmorphend != 0)
4770 lefthandmorphness = 0;
4771 lefthandmorphend = 0;
4772 targetlefthandmorphness = 1;
4774 if (headmorphend != 3 && headmorphend != 5)
4777 targetheadmorphness = 1;
4781 if (howactive > typesleeping) {
4784 if (bloodtoggle && !bled) {
4785 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4787 if (bloodtoggle && !bled)
4788 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4789 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4790 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4794 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4799 if (dead == 2 || howactive > typesleeping) {
4800 //If dead, open mouth and hands
4801 if (righthandmorphend != 0)
4802 righthandmorphness = 0;
4803 righthandmorphend = 0;
4804 targetrighthandmorphness = 1;
4806 if (lefthandmorphend != 0)
4807 lefthandmorphness = 0;
4808 lefthandmorphend = 0;
4809 targetlefthandmorphness = 1;
4811 if (headmorphend != 2)
4814 targetheadmorphness = 1;
4817 if (stunned > 0 && !dead && headmorphend != 2) {
4818 if (headmorphend != 4)
4821 targetheadmorphness = 1;
4824 if (damage > damagetolerance && !dead) {
4827 unconscioustime = 0;
4829 if (creature == wolftype) {
4830 award_bonus(0, Wolfbonus);
4835 if (weaponactive != -1) {
4836 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4837 weapons[weaponids[0]].velocity.x += .01;
4840 weaponids[0] = weaponids[num_weapons];
4841 if (weaponstuck == num_weapons)
4845 for (unsigned i = 0; i < Person::players.size(); i++) {
4846 Person::players[i]->wentforweapon = 0;
4852 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4861 damage -= multiplier * 13;
4863 permanentdamage -= multiplier * 4;
4864 if (isIdle() || isCrouch()) {
4866 permanentdamage -= multiplier * 4;
4870 if (permanentdamage < 0)
4871 permanentdamage = 0;
4872 if (superpermanentdamage < 0)
4873 superpermanentdamage = 0;
4874 if (permanentdamage < superpermanentdamage) {
4875 permanentdamage = superpermanentdamage;
4877 if (damage < permanentdamage) {
4878 damage = permanentdamage;
4880 if (dead == 1 && damage < damagetolerance) {
4884 for (int i = 0; i < skeleton.num_joints; i++) {
4885 skeleton.joints[i].velocity = 0;
4888 if (permanentdamage > damagetolerance && dead != 2) {
4891 if (weaponactive != -1) {
4892 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4893 weapons[weaponids[0]].velocity.x += .01;
4896 weaponids[0] = weaponids[num_weapons];
4897 if (weaponstuck == num_weapons)
4901 for (unsigned i = 0; i < Person::players.size(); i++) {
4902 Person::players[i]->wentforweapon = 0;
4908 if (!dead && creature == wolftype) {
4909 award_bonus(0, Wolfbonus);
4912 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4913 award_bonus(id, touchofdeath);
4914 if (id != 0 && unconscioustime > .1) {
4922 emit_sound_at(breaksound, coords);
4925 if (skeleton.free == 1) {
4927 pause_sound(whooshsound);
4930 //If knocked over, open hands and close mouth
4931 if (righthandmorphend != 0)
4932 righthandmorphness = 0;
4933 righthandmorphend = 0;
4934 targetrighthandmorphness = 1;
4936 if (lefthandmorphend != 0)
4937 lefthandmorphness = 0;
4938 lefthandmorphend = 0;
4939 targetlefthandmorphness = 1;
4941 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4942 if (headmorphend != 0)
4945 targetheadmorphness = 1;
4949 skeleton.DoGravity(&scale);
4951 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4952 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4953 award_bonus(id, deepimpact);
4954 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4958 for (j = 0; j < skeleton.num_joints; j++) {
4959 average += skeleton.joints[j].position;
4963 coords += average * scale;
4964 for (j = 0; j < skeleton.num_joints; j++) {
4965 skeleton.joints[j].position -= average;
4967 average /= multiplier;
4970 for (int i = 0; i < skeleton.num_joints; i++) {
4971 velocity += skeleton.joints[i].velocity * scale;
4973 velocity /= skeleton.num_joints;
4975 if (!isnormal(velocity.x) && velocity.x) {
4979 if (findLength(&average) < 10 && dead && skeleton.free) {
4980 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4981 if (skeleton.longdead > 2000) {
4982 if (skeleton.longdead > 6000) {
4984 pause_sound(whooshsound);
4989 if (dead == 2 && bloodloss < damagetolerance) {
4991 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4993 if (bloodtoggle && !bled) {
4994 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4996 if (bloodtoggle && !bled)
4997 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4998 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4999 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5000 float size = .2 * 1.2;
5003 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5007 if (dead == 2 && bloodloss >= damagetolerance) {
5009 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5012 if (bloodtoggle && !bled) {
5013 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5015 if (bloodtoggle && !bled)
5016 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5017 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5018 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5022 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5029 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5030 bool canrecover = 1;
5031 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5032 startpoint = coords;
5035 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5037 if (velocity.y < -30)
5039 for (i = 0; i < objects.numobjects; i++) {
5040 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5041 colviewer = startpoint;
5042 coltarget = endpoint;
5043 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5052 terrainnormal = jointPos(groin) - jointPos(abdomen);
5053 if (joint(groin).locked && joint(abdomen).locked) {
5054 terrainnormal = jointPos(groin) - jointPos(abdomen);
5055 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5057 if (joint(abdomen).locked && joint(neck).locked) {
5058 terrainnormal = jointPos(abdomen) - jointPos(neck);
5059 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5061 if (joint(groin).locked && joint(neck).locked) {
5062 terrainnormal = jointPos(groin) - jointPos(neck);
5063 middle = (jointPos(groin) + jointPos(neck)) / 2;
5065 Normalise(&terrainnormal);
5067 targetyaw = -asin(0 - terrainnormal.x);
5068 targetyaw *= 360 / 6.28;
5069 if (terrainnormal.z < 0)
5070 targetyaw = 180 - targetyaw;
5074 animTarget = flipanim;
5075 crouchtogglekeydown = 1;
5080 animCurrent = tempanim;
5084 for (int i = 0; i < skeleton.num_joints; i++) {
5085 tempanimation.position[i][0] = skeleton.joints[i].position;
5086 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5091 if (findLength(&average) < 10 && !dead && skeleton.free) {
5092 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5093 if (skeleton.longdead > (damage + 500) * 1.5) {
5095 pause_sound(whooshsound);
5101 terrainnormal = jointPos(groin) - jointPos(abdomen);
5102 if (joint(groin).locked && joint(abdomen).locked) {
5103 terrainnormal = jointPos(groin) - jointPos(abdomen);
5104 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5106 if (joint(abdomen).locked && joint(neck).locked) {
5107 terrainnormal = jointPos(abdomen) - jointPos(neck);
5108 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5110 if (joint(groin).locked && joint(neck).locked) {
5111 terrainnormal = jointPos(groin) - jointPos(neck);
5112 middle = (jointPos(groin) + jointPos(neck)) / 2;
5114 Normalise(&terrainnormal);
5116 targetyaw = -asin(0 - terrainnormal.x);
5117 targetyaw *= 360 / 6.28;
5118 if (terrainnormal.z < 0)
5119 targetyaw = 180 - targetyaw;
5122 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5125 if (skeleton.forward.y < 0) {
5126 animTarget = getupfrombackanim;
5130 if (skeleton.forward.y > -.3) {
5131 animTarget = getupfromfrontanim;
5139 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5140 animTarget = rollanim;
5141 targetyaw = lookyaw;
5158 if ( !leftkeydown && !rightkeydown)
5165 if (abs(targettilt2) > 50)
5167 animCurrent = tempanim;
5170 tilt2 = targettilt2;
5172 if (middle.y > 0 && animTarget != rollanim)
5173 targetoffset.y = middle.y + 1;
5175 for (int i = 0; i < skeleton.num_joints; i++) {
5176 tempanimation.position[i][0] = skeleton.joints[i].position;
5177 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5184 if (num_weapons > 0)
5185 if (weapons[0].getType() == staff)
5187 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5188 if (velocity.y > -30) {
5190 tempvelocity = velocity;
5191 Normalise(&tempvelocity);
5192 targetyaw = -asin(0 - tempvelocity.x);
5193 targetyaw *= 360 / 6.28;
5195 targetyaw = 180 - targetyaw;
5199 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5200 animTarget = rollanim;
5203 animTarget = backhandspringanim;
5209 emit_sound_at(movewhooshsound, coords, 128.);
5211 animCurrent = animTarget;
5212 frameCurrent = frameTarget - 1;
5224 if (skeleton.freefall == 0)
5229 if (aitype != passivetype || skeleton.free == 1)
5230 if (findLengthfast(&velocity) > .1)
5231 for (i = 0; i < objects.numobjects; i++) {
5232 if (objects.type[i] == firetype)
5233 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) {
5235 if (!objects.onfire[i]) {
5236 emit_sound_at(firestartsound, objects.position[i]);
5238 objects.onfire[i] = 1;
5241 if (objects.onfire[i]) {
5246 if (objects.type[i] == bushtype)
5247 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) {
5249 if (!objects.onfire[i]) {
5250 emit_sound_at(firestartsound, objects.position[i]);
5252 objects.onfire[i] = 1;
5256 if (objects.onfire[i]) {
5260 if (objects.messedwith[i] <= 0) {
5264 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5267 addEnvSound(coords, 4 * findLength(&velocity));
5271 if (environment == grassyenvironment)
5272 howmany = findLength(&velocity) * 4;
5273 if (environment == snowyenvironment)
5274 howmany = findLength(&velocity) * 2;
5276 if (environment != desertenvironment)
5277 for (j = 0; j < howmany; j++) {
5278 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5279 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5280 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5283 pos.x += float(abs(Random() % 100) - 50) / 200;
5284 pos.y += float(abs(Random() % 100) - 50) / 200;
5285 pos.z += float(abs(Random() % 100) - 50) / 200;
5286 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);
5287 Sprite::setLastSpriteSpecial(1);
5289 howmany = findLength(&velocity) * 4;
5291 if (environment == snowyenvironment)
5292 for (j = 0; j < howmany; j++) {
5293 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5294 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5295 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5298 pos.x += float(abs(Random() % 100) - 50) / 200;
5299 pos.y += float(abs(Random() % 100) - 50) / 200;
5300 pos.z += float(abs(Random() % 100) - 50) / 200;
5301 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5302 Sprite::setLastSpriteSpecial(2);
5305 objects.rotx[i] += velocity.x * multiplier * 6;
5306 objects.roty[i] += velocity.z * multiplier * 6;
5307 objects.messedwith[i] = .5;
5310 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5311 if (objects.pitch[i] == 0)
5314 tempcoord = coords - objects.position[i];
5315 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5316 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5317 tempcoord += objects.position[i];
5319 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]) {
5320 if (objects.messedwith[i] <= 0) {
5324 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5327 addEnvSound(coords, 4 * findLength(&velocity));
5331 if (environment == grassyenvironment)
5332 howmany = findLength(&velocity) * 4;
5333 if (environment == snowyenvironment)
5334 howmany = findLength(&velocity) * 2;
5336 if (environment != desertenvironment)
5337 for (j = 0; j < howmany; j++) {
5338 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5339 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5340 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5342 pos += velocity * .1;
5344 pos.x += float(abs(Random() % 100) - 50) / 150;
5345 pos.y += float(abs(Random() % 100) - 50) / 150;
5346 pos.z += float(abs(Random() % 100) - 50) / 150;
5347 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);
5348 Sprite::setLastSpriteSpecial(1);
5350 howmany = findLength(&velocity) * 4;
5352 if (environment == snowyenvironment)
5353 for (j = 0; j < howmany; j++) {
5354 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5355 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5356 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5358 pos += velocity * .1;
5360 pos.x += float(abs(Random() % 100) - 50) / 150;
5361 pos.y += float(abs(Random() % 100) - 50) / 150;
5362 pos.z += float(abs(Random() % 100) - 50) / 150;
5363 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5364 Sprite::setLastSpriteSpecial(2);
5367 objects.messedwith[i] = .5;
5372 if (!skeleton.free) {
5375 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5378 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5380 if (tutoriallevel == 1 && id != 0)
5382 if (play && aitype != playercontrolled) {
5383 int whichsound = -1;
5384 i = abs(Random() % 4);
5385 if (speechdelay <= 0) {
5386 if (creature == rabbittype) {
5388 whichsound = rabbitchitter;
5390 whichsound = rabbitchitter2;
5392 if (creature == wolftype) {
5394 whichsound = growlsound;
5396 whichsound = growl2sound;
5401 if (whichsound != -1) {
5402 emit_sound_at(whichsound, coords);
5406 if (animTarget == staggerbackhighanim)
5408 if (animTarget == staggerbackhardanim)
5410 staggerdelay -= multiplier;
5411 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5413 if (velocity.y < -30 && animTarget == jumpdownanim)
5415 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5416 animTarget = getIdle();
5420 weaponmissdelay -= multiplier;
5421 highreversaldelay -= multiplier;
5422 lowreversaldelay -= multiplier;
5423 lastcollide -= multiplier;
5424 skiddelay -= multiplier;
5425 if (!isnormal(velocity.x) && velocity.x) {
5428 if (!isnormal(targettilt) && targettilt) {
5431 if (!isnormal(targettilt2) && targettilt2) {
5434 if (!isnormal(targetyaw) && targetyaw) {
5438 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5439 //open hands and close mouth
5440 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5441 righthandmorphness = 0;
5442 righthandmorphend = 0;
5443 targetrighthandmorphness = 1;
5446 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5447 lefthandmorphness = 0;
5448 lefthandmorphend = 0;
5449 targetlefthandmorphness = 1;
5452 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5455 targetheadmorphness = 1;
5459 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) {
5460 //open hands and mouth
5461 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5462 righthandmorphness = 0;
5463 righthandmorphend = 0;
5464 targetrighthandmorphness = 1;
5467 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5468 lefthandmorphness = 0;
5469 lefthandmorphend = 0;
5470 targetlefthandmorphness = 1;
5473 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5476 targetheadmorphness = 1;
5480 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5481 //close hands and mouth
5482 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5483 righthandmorphness = 0;
5484 righthandmorphend = 1;
5485 targetrighthandmorphness = 1;
5488 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5489 lefthandmorphness = 0;
5490 lefthandmorphend = 1;
5491 targetlefthandmorphness = 1;
5494 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5497 targetheadmorphness = 1;
5501 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) {
5502 //close hands and yell
5503 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5504 righthandmorphness = 0;
5505 righthandmorphend = 1;
5506 targetrighthandmorphness = 1;
5509 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5510 lefthandmorphness = 0;
5511 lefthandmorphend = 1;
5512 targetlefthandmorphness = 1;
5515 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5518 targetheadmorphness = 1;
5525 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5526 (victim->aitype != searchtype) && (aitype != passivetype) &&
5527 (aitype != searchtype) && (victim->id < Person::players.size())) {
5528 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5532 if (!dead && animTarget != hurtidleanim)
5533 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5534 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5537 targetheadmorphness = 1;
5541 if (weaponactive != -1) {
5542 if (weapons[weaponids[weaponactive]].getType() != staff) {
5543 righthandmorphstart = 1;
5544 righthandmorphend = 1;
5546 if (weapons[weaponids[weaponactive]].getType() == staff) {
5547 righthandmorphstart = 2;
5548 righthandmorphend = 2;
5550 targetrighthandmorphness = 1;
5553 terrainnormal = terrain.getNormal(coords.x, coords.z);
5555 if (animation[animTarget].attack != reversal) {
5556 if (!isnormal(coords.x))
5564 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5565 facing = flatfacing;
5566 ReflectVector(&facing, terrainnormal);
5569 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5571 targettilt2 = -facing.y * 20;
5576 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5578 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5579 flatvelocity = velocity;
5581 flatvelspeed = findLength(&flatvelocity);
5582 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5583 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5588 if (targettilt > 25)
5590 if (targettilt < -25)
5594 if (targettilt2 > 45)
5596 if (targettilt2 < -45)
5598 if (abs(tilt2 - targettilt2) < multiplier * 400)
5599 tilt2 = targettilt2;
5600 else if (tilt2 > targettilt2) {
5601 tilt2 -= multiplier * 400;
5602 } else if (tilt2 < targettilt2) {
5603 tilt2 += multiplier * 400;
5605 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5612 if (!isnormal(targettilt) && targettilt) {
5615 if (!isnormal(targettilt2) && targettilt2) {
5620 if (animTarget == rabbittackleanim) {
5621 velocity += facing * multiplier * speed * 700 * scale;
5622 velspeed = findLength(&velocity);
5623 if (velspeed > speed * 65 * scale) {
5624 velocity /= velspeed;
5625 velspeed = speed * 65 * scale;
5626 velocity *= velspeed;
5628 velocity.y += gravity * multiplier * 20;
5629 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5630 velspeed = findLength(&velocity);
5631 velocity = flatfacing * velspeed;
5633 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5634 if (isRun() || animTarget == rabbitkickanim) {
5635 velocity += facing * multiplier * speed * 700 * scale;
5636 velspeed = findLength(&velocity);
5637 if (velspeed > speed * 45 * scale) {
5638 velocity /= velspeed;
5639 velspeed = speed * 45 * scale;
5640 velocity *= velspeed;
5642 velocity.y += gravity * multiplier * 20;
5643 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5644 velspeed = findLength(&velocity);
5645 if (velspeed < speed * 30 * scale)
5646 velspeed = speed * 30 * scale;
5647 velocity = flatfacing * velspeed;
5649 } else if (isRun()) {
5650 velocity += facing * multiplier * speed * 700 * scale;
5651 velspeed = findLength(&velocity);
5652 if (creature == rabbittype) {
5653 if (velspeed > speed * 55 * scale) {
5654 velocity /= velspeed;
5655 velspeed = speed * 55 * scale;
5656 velocity *= velspeed;
5659 if (creature == wolftype) {
5660 if (velspeed > speed * 75 * scale) {
5661 velocity /= velspeed;
5662 velspeed = speed * 75 * scale;
5663 velocity *= velspeed;
5666 velocity.y += gravity * multiplier * 20;
5667 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5668 velspeed = findLength(&velocity);
5669 velocity = flatfacing * velspeed;
5672 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5673 velocity += facing * multiplier * speed * 700 * scale;
5674 velspeed = findLength(&velocity);
5675 if (velspeed > speed * 45 * scale) {
5676 velocity /= velspeed;
5677 velspeed = speed * 45 * scale;
5678 velocity *= velspeed;
5680 velocity.y += gravity * multiplier * 20;
5681 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5682 velspeed = findLength(&velocity);
5683 velocity = flatfacing * velspeed;
5686 if (animTarget == sneakanim || animTarget == walkanim) {
5687 velocity += facing * multiplier * speed * 700 * scale;
5688 velspeed = findLength(&velocity);
5689 if (velspeed > speed * 12 * scale) {
5690 velocity /= velspeed;
5691 velspeed = speed * 12 * scale;
5692 velocity *= velspeed;
5694 velocity.y += gravity * multiplier * 20;
5695 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5696 velspeed = findLength(&velocity);
5697 velocity = flatfacing * velspeed;
5700 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5701 velocity += facing * multiplier * speed * 700 * scale;
5702 velspeed = findLength(&velocity);
5703 if (velspeed > speed * 2 * scale) {
5704 velocity /= velspeed;
5705 velspeed = speed * 2 * scale;
5706 velocity *= velspeed;
5708 velocity.y += gravity * multiplier * 20;
5709 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5710 velspeed = findLength(&velocity);
5711 velocity = flatfacing * velspeed;
5715 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5716 velocity -= facing * multiplier * speed * 700 * scale;
5717 velspeed = findLength(&velocity);
5718 if (velspeed > speed * 2 * scale) {
5719 velocity /= velspeed;
5720 velspeed = speed * 2 * scale;
5721 velocity *= velspeed;
5723 velocity.y += gravity * multiplier * 20;
5724 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5725 velspeed = findLength(&velocity);
5726 velocity = flatfacing * velspeed * -1;
5729 if (animTarget == fightsidestep) {
5730 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5731 velspeed = findLength(&velocity);
5732 if (velspeed > speed * 12 * scale) {
5733 velocity /= velspeed;
5734 velspeed = speed * 12 * scale;
5735 velocity *= velspeed;
5737 velocity.y += gravity * multiplier * 20;
5738 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5739 velspeed = findLength(&velocity);
5740 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5743 if (animTarget == staggerbackhighanim) {
5744 coords -= facing * multiplier * speed * 16 * scale;
5747 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5748 coords -= facing * multiplier * speed * 20 * scale;
5752 if (animTarget == backhandspringanim) {
5753 //coords-=facing*multiplier*50*scale;
5754 velocity += facing * multiplier * speed * 700 * scale * -1;
5755 velspeed = findLength(&velocity);
5756 if (velspeed > speed * 50 * scale) {
5757 velocity /= velspeed;
5758 velspeed = speed * 50 * scale;
5759 velocity *= velspeed;
5761 velocity.y += gravity * multiplier * 20;
5762 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5763 velspeed = findLength(&velocity);
5764 velocity = flatfacing * velspeed * -1;
5766 if (animTarget == dodgebackanim) {
5767 //coords-=facing*multiplier*50*scale;
5768 velocity += facing * multiplier * speed * 700 * scale * -1;
5769 velspeed = findLength(&velocity);
5770 if (velspeed > speed * 60 * scale) {
5771 velocity /= velspeed;
5772 velspeed = speed * 60 * scale;
5773 velocity *= velspeed;
5775 velocity.y += gravity * multiplier * 20;
5776 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5777 velspeed = findLength(&velocity);
5778 velocity = flatfacing * velspeed * -1;
5781 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5782 velspeed = findLength(&velocity);
5786 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5787 velocity.y += gravity * multiplier;
5790 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5791 coords += velocity * multiplier;
5793 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5794 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5797 if (animTarget == jumpupanim) {
5799 animTarget = getIdle();
5806 pause_sound(whooshsound);
5807 OPENAL_SetVolume(channels[whooshsound], 0);
5810 if (animTarget == jumpdownanim || isFlip()) {
5811 if (isFlip())jumppower = -4;
5812 animTarget = getLanding();
5813 emit_sound_at(landsound, coords, 128.);
5816 addEnvSound(coords);
5821 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5822 coords.y += gravity * multiplier * 2;
5823 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5824 coords.y = terrain.getHeight(coords.x, coords.z);
5829 if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || animation[animTarget].attack || (animTarget == rollanim && animation[animTarget].label[frameTarget] == 6)) {
5830 velspeed = findLength(&velocity);
5832 if (velspeed < multiplier * 300 * scale) {
5835 velocity -= velocity / velspeed * multiplier * 300 * scale;
5836 if (velspeed > 5 && (isLanding() || isLandhard())) {
5837 skiddingdelay += multiplier;
5838 if (skiddelay <= 0) {
5839 FootLand(leftfoot, .5);
5840 FootLand(rightfoot, .5);
5848 velspeed = findLength(&velocity);
5850 if (velspeed < multiplier * 600 * scale) {
5853 velocity -= velocity / velspeed * multiplier * 600 * scale;
5855 if (velspeed > 5 && (isLanding() || isLandhard())) {
5856 skiddingdelay += multiplier;
5857 if (skiddelay <= 0) {
5858 FootLand(leftfoot, .5);
5859 FootLand(rightfoot, .5);
5866 if (skiddingdelay < 0)
5867 skiddingdelay += multiplier;
5868 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5870 if (!onterrain || environment == grassyenvironment) {
5871 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5873 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5877 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5878 terrainnormal = victim->coords - coords;
5879 Normalise(&terrainnormal);
5880 targetyaw = -asin(0 - terrainnormal.x);
5881 targetyaw *= 360 / 6.28;
5882 if (terrainnormal.z < 0)
5883 targetyaw = 180 - targetyaw;
5884 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5887 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5888 targetyaw = victim->targetyaw;
5890 if (animTarget == rabbittacklinganim) {
5891 coords = victim->coords;
5894 skeleton.oldfree = skeleton.free;
5898 midterrain.x = terrain.size * terrain.scale / 2;
5899 midterrain.z = terrain.size * terrain.scale / 2;
5900 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5902 tempposit = coords - midterrain;
5904 Normalise(&tempposit);
5905 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5906 coords.x = tempposit.x + midterrain.x;
5907 coords.z = tempposit.z + midterrain.z;
5913 * inverse kinematics helper function
5915 void IKHelper(Person *p, float interp)
5917 XYZ point, change, change2;
5918 float heightleft, heightright;
5920 // TODO: implement localToWorld and worldToLocal
5921 // but keep in mind it won't be the same math if player is ragdolled or something
5922 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5923 // then comb through code for places where to use it
5925 // point = localToWorld(jointPos(leftfoot))
5926 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5927 // adjust height of foot
5928 heightleft = terrain.getHeight(point.x, point.z) + .04;
5929 point.y = heightleft;
5930 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5931 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5932 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5933 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5934 // move ankle along with foot
5935 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5936 // average knee pos between old and new pos
5937 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5939 // do same as above for right leg
5940 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5941 heightright = terrain.getHeight(point.x, point.z) + .04;
5942 point.y = heightright;
5943 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5944 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5945 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5946 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5947 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5949 // fix up skeleton now that we've moved body parts?
5950 p->skeleton.DoConstraints(&p->coords, &p->scale);
5957 int Person::DrawSkeleton()
5959 int oldplayerdetail;
5960 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5961 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5971 glAlphaFunc(GL_GREATER, 0.0001);
5973 float terrainheight;
5977 if (!isnormal(tilt))
5979 if (!isnormal(tilt2))
5981 oldplayerdetail = playerdetail;
5983 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5986 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5989 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5994 if (playerdetail != oldplayerdetail) {
5996 normalsupdatedelay = 0;
5998 static float updatedelaychange;
5999 static float morphness;
6000 static float framemult;
6002 skeleton.FindForwards();
6003 if (howactive == typesittingwall) {
6004 skeleton.specialforward[1] = 0;
6005 skeleton.specialforward[1].z = 1;
6011 static int weaponattachmuscle;
6012 static int weaponrotatemuscle;
6013 static XYZ weaponpoint;
6014 static int start, endthing;
6015 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6016 if (!isSleeping() && !isSitting()) {
6017 // TODO: give these meaningful names
6018 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6019 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6020 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6021 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6023 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6025 if (creature == wolftype)
6029 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6030 IKHelper(this, target);
6031 if (creature == wolftype)
6032 IKHelper(this, target);
6035 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6036 IKHelper(this, 1 - target);
6037 if (creature == wolftype)
6038 IKHelper(this, 1 - target);
6042 if (!skeleton.free && (!animation[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || animation[animTarget].label[frameTarget] == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
6045 targetheadyaw = -targetyaw;
6046 targetheadpitch = 0;
6047 if (animation[animTarget].attack == 3)
6048 targetheadyaw += 180;
6050 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6051 skeleton.drawmodel.vertex[i] = 0;
6052 skeleton.drawmodel.vertex[i].y = 999;
6054 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6055 skeleton.drawmodellow.vertex[i] = 0;
6056 skeleton.drawmodellow.vertex[i].y = 999;
6058 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6059 skeleton.drawmodelclothes.vertex[i] = 0;
6060 skeleton.drawmodelclothes.vertex[i].y = 999;
6062 for (int i = 0; i < skeleton.num_muscles; i++) {
6063 // convenience renames
6064 const int p1 = skeleton.muscles[i].parent1->label;
6065 const int p2 = skeleton.muscles[i].parent2->label;
6067 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6072 if (p1 == righthand || p2 == righthand) {
6073 morphness = righthandmorphness;
6074 start = righthandmorphstart;
6075 endthing = righthandmorphend;
6077 if (p1 == lefthand || p2 == lefthand) {
6078 morphness = lefthandmorphness;
6079 start = lefthandmorphstart;
6080 endthing = lefthandmorphend;
6082 if (p1 == head || p2 == head) {
6083 morphness = headmorphness;
6084 start = headmorphstart;
6085 endthing = headmorphend;
6087 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6088 morphness = chestmorphness;
6089 start = chestmorphstart;
6090 endthing = chestmorphend;
6092 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6093 morphness = tailmorphness;
6094 start = tailmorphstart;
6095 endthing = tailmorphend;
6098 skeleton.FindRotationMuscle(i, animTarget);
6099 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6100 glMatrixMode(GL_MODELVIEW);
6104 glRotatef(tilt2, 1, 0, 0);
6106 glRotatef(tilt, 0, 0, 1);
6109 glTranslatef(mid.x, mid.y, mid.z);
6111 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6112 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6114 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6115 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6117 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6118 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6120 if (playerdetail || skeleton.free == 3) {
6121 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6122 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6123 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6124 glMatrixMode(GL_MODELVIEW);
6126 if (p1 == abdomen || p2 == abdomen)
6127 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6128 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6129 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6130 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6131 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6132 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6133 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6134 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6135 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6136 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6137 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6138 if (p1 == head || p2 == head)
6139 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6140 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6141 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6142 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6143 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6144 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6145 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6149 if (!playerdetail || skeleton.free == 3) {
6150 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6151 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6152 glMatrixMode(GL_MODELVIEW);
6154 if (p1 == abdomen || p2 == abdomen)
6155 glTranslatef(v0.x * proportionbody.x,
6156 v0.y * proportionbody.y,
6157 v0.z * proportionbody.z);
6158 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6159 glTranslatef(v0.x * proportionarms.x,
6160 v0.y * proportionarms.y,
6161 v0.z * proportionarms.z);
6162 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6163 glTranslatef(v0.x * proportionlegs.x,
6164 v0.y * proportionlegs.y,
6165 v0.z * proportionlegs.z);
6166 if (p1 == head || p2 == head)
6167 glTranslatef(v0.x * proportionhead.x,
6168 v0.y * proportionhead.y,
6169 v0.z * proportionhead.z);
6171 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6172 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6173 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6174 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6180 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6181 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6183 glMatrixMode(GL_MODELVIEW);
6187 glRotatef(tilt2, 1, 0, 0);
6189 glRotatef(tilt, 0, 0, 1);
6190 glTranslatef(mid.x, mid.y, mid.z);
6191 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6192 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6194 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6195 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6197 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6198 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6200 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6201 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6202 glMatrixMode(GL_MODELVIEW);
6204 if (p1 == abdomen || p2 == abdomen)
6205 glTranslatef(v0.x * proportionbody.x,
6206 v0.y * proportionbody.y,
6207 v0.z * proportionbody.z);
6208 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6209 glTranslatef(v0.x * proportionarms.x,
6210 v0.y * proportionarms.y,
6211 v0.z * proportionarms.z);
6212 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6213 glTranslatef(v0.x * proportionlegs.x,
6214 v0.y * proportionlegs.y,
6215 v0.z * proportionlegs.z);
6216 if (p1 == head || p2 == head)
6217 glTranslatef(v0.x * proportionhead.x,
6218 v0.y * proportionhead.y,
6219 v0.z * proportionhead.z);
6220 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6221 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6222 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6223 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6228 updatedelay = 1 + (float)(Random() % 100) / 1000;
6230 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6231 normalsupdatedelay = 1;
6232 if (playerdetail || skeleton.free == 3)
6233 skeleton.drawmodel.CalculateNormals(0);
6234 if (!playerdetail || skeleton.free == 3)
6235 skeleton.drawmodellow.CalculateNormals(0);
6236 if (skeleton.clothes)
6237 skeleton.drawmodelclothes.CalculateNormals(0);
6239 if (playerdetail || skeleton.free == 3)
6240 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6241 if (!playerdetail || skeleton.free == 3)
6242 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6243 if (skeleton.clothes) {
6244 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6249 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6250 if (updatedelaychange > -realmultiplier * 30)
6251 updatedelaychange = -realmultiplier * 30;
6252 if (updatedelaychange > -framemult * 4)
6253 updatedelaychange = -framemult * 4;
6254 if (skeleton.free == 1)
6255 updatedelaychange *= 6;
6257 updatedelaychange *= 8;
6258 updatedelay += updatedelaychange;
6260 glMatrixMode(GL_MODELVIEW);
6262 glTranslatef(coords.x, coords.y - .02, coords.z);
6263 if (!skeleton.free) {
6264 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6265 glRotatef(yaw, 0, 1, 0);
6269 glColor4f(.4, 1, .4, 1);
6270 glDisable(GL_LIGHTING);
6271 glDisable(GL_TEXTURE_2D);
6274 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6275 XYZ &v0 = skeleton.drawmodel.vertex[i];
6276 glVertex3f(v0.x, v0.y, v0.z);
6282 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6283 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6284 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6285 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6286 glVertex3f(v0.x, v0.y, v0.z);
6287 glVertex3f(v1.x, v1.y, v1.z);
6288 glVertex3f(v1.x, v1.y, v1.z);
6289 glVertex3f(v2.x, v2.y, v2.z);
6290 glVertex3f(v2.x, v2.y, v2.z);
6291 glVertex3f(v0.x, v0.y, v0.z);
6297 terrainlight = terrain.getLighting(coords.x, coords.z);
6298 distance = distsq(&viewer, &coords);
6299 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6303 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6304 if (terrainheight < 1)
6306 if (terrainheight > 1.7)
6307 terrainheight = 1.7;
6309 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6310 glDisable(GL_BLEND);
6311 glAlphaFunc(GL_GREATER, 0.0001);
6312 glEnable(GL_TEXTURE_2D);
6314 glDisable(GL_TEXTURE_2D);
6315 glColor4f(.7, .35, 0, .5);
6317 glEnable(GL_LIGHTING);
6320 if (tutoriallevel && id != 0) {
6321 glColor4f(.7, .7, .7, 0.6);
6323 glEnable(GL_LIGHTING);
6325 if (canattack && cananger)
6326 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6327 glDisable(GL_TEXTURE_2D);
6328 glColor4f(1, 0, 0, 0.8);
6330 glMatrixMode(GL_TEXTURE);
6332 glTranslatef(0, -smoketex, 0);
6333 glTranslatef(-smoketex, 0, 0);
6337 if ((tutoriallevel && id != 0))
6338 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6340 skeleton.drawmodel.draw();
6343 if (!playerdetail) {
6344 if ((tutoriallevel && id != 0))
6345 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6347 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6350 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6351 if (tutoriallevel && id != 0) {
6353 glMatrixMode(GL_MODELVIEW);
6354 glEnable(GL_TEXTURE_2D);
6355 glColor4f(.7, .7, .7, 0.6);
6357 glEnable(GL_LIGHTING);
6359 if (canattack && cananger)
6360 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6361 glDisable(GL_TEXTURE_2D);
6362 glColor4f(1, 0, 0, 0.8);
6364 glMatrixMode(GL_TEXTURE);
6366 glTranslatef(0, -smoketex * .6, 0);
6367 glTranslatef(smoketex * .6, 0, 0);
6370 if ((tutoriallevel && id != 0))
6371 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6373 skeleton.drawmodel.draw();
6376 if (!playerdetail) {
6377 if ((tutoriallevel && id != 0))
6378 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6380 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6385 if (tutoriallevel && id != 0) {
6387 glMatrixMode(GL_MODELVIEW);
6388 glEnable(GL_TEXTURE_2D);
6390 if (skeleton.clothes) {
6394 skeleton.drawmodelclothes.draw();
6396 skeleton.drawmodelclothes.drawimmediate();
6402 if (num_weapons > 0) {
6403 for (k = 0; k < num_weapons; k++) {
6405 if (weaponactive == k) {
6406 if (weapons[i].getType() != staff) {
6407 for (j = 0; j < skeleton.num_muscles; j++) {
6408 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6409 weaponattachmuscle = j;
6412 for (j = 0; j < skeleton.num_muscles; j++) {
6413 if ((skeleton.muscles[j].parent1->label == rightwrist || skeleton.muscles[j].parent2->label == rightwrist) && (skeleton.muscles[j].parent1->label != righthand && skeleton.muscles[j].parent2->label != righthand) && skeleton.muscles[j].numvertices > 0) {
6414 weaponrotatemuscle = j;
6417 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6418 if (creature == wolftype)
6419 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6421 if (weapons[i].getType() == staff) {
6422 for (j = 0; j < skeleton.num_muscles; j++) {
6423 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6424 weaponattachmuscle = j;
6427 for (j = 0; j < skeleton.num_muscles; j++) {
6428 if ((skeleton.muscles[j].parent1->label == rightelbow || skeleton.muscles[j].parent2->label == rightelbow) && (skeleton.muscles[j].parent1->label != rightshoulder && skeleton.muscles[j].parent2->label != rightshoulder) && skeleton.muscles[j].numvertices > 0) {
6429 weaponrotatemuscle = j;
6432 //weaponpoint=jointPos(rightwrist);
6433 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6434 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6435 XYZ tempnormthing, vec1, vec2;
6436 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6437 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6438 CrossProduct(&vec1, &vec2, &tempnormthing);
6439 Normalise(&tempnormthing);
6440 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6441 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6444 if (weaponactive != k && weaponstuck != k) {
6445 if (weapons[i].getType() == knife)
6446 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6447 if (weapons[i].getType() == sword)
6448 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6449 if (weapons[i].getType() == staff)
6450 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6451 for (j = 0; j < skeleton.num_muscles; j++) {
6452 if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].numvertices > 0) {
6453 weaponrotatemuscle = j;
6457 if (weaponstuck == k) {
6458 if (weaponstuckwhere == 0)
6459 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6461 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6462 for (j = 0; j < skeleton.num_muscles; j++) {
6463 if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].numvertices > 0) {
6464 weaponrotatemuscle = j;
6468 if (skeleton.free) {
6469 weapons[i].position = weaponpoint * scale + coords;
6470 weapons[i].bigrotation = 0;
6471 weapons[i].bigtilt = 0;
6472 weapons[i].bigtilt2 = 0;
6474 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;
6475 weapons[i].bigrotation = yaw;
6476 weapons[i].bigtilt = tilt;
6477 weapons[i].bigtilt2 = tilt2;
6479 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6480 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6481 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6482 if (weaponactive == k) {
6483 if (weapons[i].getType() == knife) {
6484 weapons[i].smallrotation = 180;
6485 weapons[i].smallrotation2 = 0;
6486 if (isCrouch() || wasCrouch()) {
6487 weapons[i].smallrotation2 = 20;
6489 if (animTarget == hurtidleanim) {
6490 weapons[i].smallrotation2 = 50;
6492 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6493 XYZ temppoint1, temppoint2;
6496 temppoint1 = jointPos(righthand);
6497 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6498 distance = findDistance(&temppoint1, &temppoint2);
6499 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6500 weapons[i].rotation2 *= 360 / 6.28;
6503 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6504 weapons[i].rotation1 *= 360 / 6.28;
6505 weapons[i].rotation3 = 0;
6506 weapons[i].smallrotation = -90;
6507 weapons[i].smallrotation2 = 0;
6508 if (temppoint1.x > temppoint2.x)
6509 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6511 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6512 XYZ temppoint1, temppoint2;
6515 temppoint1 = jointPos(righthand);
6516 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6517 distance = findDistance(&temppoint1, &temppoint2);
6518 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6519 weapons[i].rotation2 *= 360 / 6.28;
6522 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6523 weapons[i].rotation1 *= 360 / 6.28;
6524 weapons[i].rotation3 = 0;
6525 weapons[i].smallrotation = 90;
6526 weapons[i].smallrotation2 = 0;
6527 if (temppoint1.x > temppoint2.x)
6528 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6530 if (animTarget == knifethrowanim) {
6531 weapons[i].smallrotation = 90;
6532 //weapons[i].smallrotation2=-90;
6533 weapons[i].smallrotation2 = 0;
6534 weapons[i].rotation1 = 0;
6535 weapons[i].rotation2 = 0;
6536 weapons[i].rotation3 = 0;
6538 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6539 weapons[i].smallrotation = -90;
6540 weapons[i].rotation1 = 0;
6541 weapons[i].rotation2 = 0;
6542 weapons[i].rotation3 = 0;
6545 if (weapons[i].getType() == sword) {
6546 weapons[i].smallrotation = 0;
6547 weapons[i].smallrotation2 = 0;
6548 if (animTarget == knifethrowanim) {
6549 weapons[i].smallrotation = -90;
6550 weapons[i].smallrotation2 = 0;
6551 weapons[i].rotation1 = 0;
6552 weapons[i].rotation2 = 0;
6553 weapons[i].rotation3 = 0;
6555 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)) {
6556 XYZ temppoint1, temppoint2;
6559 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6560 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (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;
6575 if (weapons[i].getType() == staff) {
6576 weapons[i].smallrotation = 100;
6577 weapons[i].smallrotation2 = 0;
6578 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6579 XYZ temppoint1, temppoint2;
6582 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6583 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6584 distance = findDistance(&temppoint1, &temppoint2);
6585 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6586 weapons[i].rotation2 *= 360 / 6.28;
6589 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6590 weapons[i].rotation1 *= 360 / 6.28;
6591 weapons[i].rotation3 = 0;
6592 weapons[i].smallrotation = 90;
6593 weapons[i].smallrotation2 = 0;
6594 if (temppoint1.x > temppoint2.x)
6595 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6599 if (weaponactive != k && weaponstuck != k) {
6600 if (weapons[i].getType() == knife) {
6601 weapons[i].smallrotation = -70;
6602 weapons[i].smallrotation2 = 10;
6604 if (weapons[i].getType() == sword) {
6605 weapons[i].smallrotation = -100;
6606 weapons[i].smallrotation2 = -8;
6608 if (weapons[i].getType() == staff) {
6609 weapons[i].smallrotation = -100;
6610 weapons[i].smallrotation2 = -8;
6613 if (weaponstuck == k) {
6614 if (weaponstuckwhere == 0)
6615 weapons[i].smallrotation = 180;
6617 weapons[i].smallrotation = 0;
6618 weapons[i].smallrotation2 = 10;
6627 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6629 if (animCurrent != animTarget)
6631 if (skeleton.free == 2)
6640 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6643 static float distance;
6644 static float olddistance;
6645 static int intersecting;
6646 static int firstintersecting;
6649 static XYZ start, end;
6650 static float slopethreshold = -.4;
6652 firstintersecting = -1;
6656 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6659 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6660 for (i = 0; i < 4; i++) {
6661 for (j = 0; j < model->TriangleNum; j++) {
6662 if (model->facenormals[j].y <= slopethreshold) {
6664 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)));
6665 if (distance < radius) {
6666 point = *p1 - model->facenormals[j] * distance;
6667 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]]))
6670 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6671 &model->vertex[model->Triangles[j].vertex[1]],
6674 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6675 &model->vertex[model->Triangles[j].vertex[2]],
6678 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6679 &model->vertex[model->Triangles[j].vertex[2]],
6682 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6686 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)) {
6687 p1->y = point.y + radius;
6688 if ((animTarget == jumpdownanim || isFlip())) {
6689 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6692 if (animTarget == jumpupanim) {
6694 animTarget = getIdle();
6701 pause_sound(whooshsound);
6702 OPENAL_SetVolume(channels[whooshsound], 0);
6705 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6708 animTarget = getLanding();
6709 emit_sound_at(landsound, coords, 128.);
6712 addEnvSound(coords);
6719 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6720 olddistance = distance;
6721 firstintersecting = j;
6726 for (j = 0; j < model->TriangleNum; j++) {
6727 if (model->facenormals[j].y > slopethreshold) {
6730 start.y -= radius / 4;
6731 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6732 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6733 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6734 distance = abs((model->facenormals[j].x * start.x)
6735 + (model->facenormals[j].y * start.y)
6736 + (model->facenormals[j].z * start.z)
6737 - ((model->facenormals[j].x * v0.x)
6738 + (model->facenormals[j].y * v0.y)
6739 + (model->facenormals[j].z * v0.z)));
6740 if (distance < radius * .5) {
6741 point = start - model->facenormals[j] * distance;
6742 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6745 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6747 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6749 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6751 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6752 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6754 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6755 if (findLengthfast(&start) < findLengthfast(&velocity))
6758 *p1 += model->facenormals[j] * (distance - radius * .5);
6761 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6762 olddistance = distance;
6763 firstintersecting = j;
6770 *p = DoRotation(*p, 0, *rotate, 0);
6773 *p1 = DoRotation(*p1, 0, *rotate, 0);
6775 return firstintersecting;
6778 void Person::takeWeapon(int weaponId)
6781 weapons[weaponId].owner = id;
6782 if (num_weapons > 0) {
6783 weaponids[num_weapons] = weaponids[0];
6786 weaponids[0] = weaponId;
6789 void Person::addClothes()
6791 if (numclothes > 0) {
6792 for (int i = 0; i < numclothes; i++) {
6799 bool Person::addClothes(const int& clothesId)
6802 const char* fileName = clothes[clothesId];
6804 GLubyte* array = &skeleton.skinText[0];
6808 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6813 float tintr = clothestintr[clothesId];
6814 float tintg = clothestintg[clothesId];
6815 float tintb = clothestintb[clothesId];
6817 if (tintr > 1) tintr = 1;
6818 if (tintg > 1) tintg = 1;
6819 if (tintb > 1) tintb = 1;
6821 if (tintr < 0) tintr = 0;
6822 if (tintg < 0) tintg = 0;
6823 if (tintb < 0) tintb = 0;
6825 int bytesPerPixel = texture.bpp / 8;
6829 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6830 if (bytesPerPixel == 3)
6832 else if ((i + 1) % 4 == 0)
6833 alphanum = texture.data[i];
6834 if ((i + 1) % 4 || bytesPerPixel == 3) {
6836 texture.data[i] *= tintr;
6838 texture.data[i] *= tintg;
6840 texture.data[i] *= tintb;
6841 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);