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 extern float multiplier;
30 extern Terrain terrain;
32 extern int environment;
34 extern FRUSTUM frustum;
36 extern float realmultiplier;
38 extern float slomodelay;
39 extern bool cellophane;
40 extern float texdetail;
41 extern float realtexdetail;
42 extern GLubyte bloodText[512 * 512 * 3];
43 extern GLubyte wolfbloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern float flashamount, flashr, flashg, flashb;
57 extern int flashdelay;
58 extern bool showpoints;
59 extern bool immediate;
61 extern bool tilt2weird;
62 extern bool tiltweird;
64 extern bool proportionweird;
65 extern bool vertexweird[6];
66 extern XYZ envsound[30];
67 extern float envsoundvol[30];
68 extern float envsoundlife[30];
69 extern int numenvsounds;
70 extern int tutoriallevel;
71 extern float smoketex;
72 extern int tutorialstage;
73 extern bool reversaltrain;
74 extern bool canattack;
76 extern float damagedealt;
78 extern float hostiletime;
80 extern int indialogue;
82 extern bool gamestarted;
84 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
97 howactive(typeactive),
99 superruntoggle(false),
100 lastattack(0), lastattack2(0), lastattack3(0),
101 currentoffset(), targetoffset(), offset(),
133 rabbitkickenabled(false),
145 superpermanentdamage(0),
159 bleedx(0), bleedy(0),
163 headyaw(0), headpitch(0),
164 targetheadyaw(0), targetheadpitch(0),
175 normalsupdatedelay(0),
178 forwardkeydown(false),
179 forwardstogglekeydown(false),
184 jumptogglekeydown(false),
185 crouchkeydown(false),
186 crouchtogglekeydown(false),
188 drawtogglekeydown(false),
190 throwtogglekeydown(false),
191 attackkeydown(false),
196 crouchkeydowntime(0),
210 whichdirection(false),
211 whichdirectiondelay(0),
212 avoidsomething(false),
221 lefthandmorphness(0),
222 righthandmorphness(0),
226 targetlefthandmorphness(0),
227 targetrighthandmorphness(0),
228 targetheadmorphness(0),
229 targetchestmorphness(0),
230 targettailmorphness(0),
231 lefthandmorphstart(0), lefthandmorphend(0),
232 righthandmorphstart(0), righthandmorphend(0),
233 headmorphstart(0), headmorphend(0),
234 chestmorphstart(0), chestmorphend(0),
235 tailmorphstart(0), tailmorphend(0),
238 highreversaldelay(0),
241 creature(rabbittype),
288 finalpathfindpoint(0),
289 targetpathfindpoint(0),
290 lastpathfindpoint(0),
291 lastpathfindpoint2(0),
292 lastpathfindpoint3(0),
293 lastpathfindpoint4(0),
309 neckspurtparticledelay(0),
313 rabbitkickragdoll(false),
326 * GameTick/doPlayerCollisions
328 void Person::CheckKick()
331 && (animTarget == rabbitkickanim
333 && victim != this->shared_from_this()
335 && animCurrent == rabbitkickanim)
336 && distsq(&coords, &victim->coords) < 1.2
337 && !victim->skeleton.free))
340 if (animation[victim->animTarget].height != lowheight) {
341 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
342 XYZ relative = velocity;
344 Normalise(&relative);
348 if (tutoriallevel != 1)
349 emit_sound_at(heavyimpactsound, victim->coords);
351 for (int i = 0; i < victim->skeleton.num_joints; i++) {
352 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
355 victim->DoDamage(100 * damagemult / victim->protectionhigh);
361 animTarget = backflipanim;
363 velocity = facing * -10;
367 resume_stream(whooshsound);
369 award_bonus(id, cannon);
370 } else if (victim->isCrouch()) {
371 animTarget = rabbitkickreversedanim;
372 animCurrent = rabbitkickreversedanim;
373 victim->animCurrent = rabbitkickreversalanim;
374 victim->animTarget = rabbitkickreversalanim;
380 victim->oldcoords = victim->coords;
381 coords = victim->coords;
382 victim->targetyaw = targetyaw;
383 victim->victim = this->shared_from_this();
390 * GameTick/doPlayerCollisions - spread fire between players
391 * GameTick/doDebugKeys - press f to ignite
392 * Person::DoStuff - spread fire from lit campfires and bushes
394 void Person::CatchFire()
396 XYZ flatfacing, flatvelocity;
398 for (int i = 0; i < 10; i++) {
399 howmany = abs(Random() % (skeleton.num_joints));
401 flatvelocity = skeleton.joints[howmany].velocity;
402 flatfacing = skeleton.joints[howmany].position * scale + coords;
404 flatvelocity = velocity;
405 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
407 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
412 emit_sound_at(firestartsound, coords);
414 emit_stream_at(stream_firesound, coords);
422 * idle animation for this creature (depending on status)
424 int Person::getIdle()
426 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
428 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
429 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
430 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
431 victim->id < Person::players.size())) {
432 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
433 if (creature == rabbittype)
434 return fightidleanim;
435 if (creature == wolftype)
438 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
439 if (weapons[weaponids[weaponactive]].getType() == knife)
440 return knifefightidleanim;
441 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
442 return swordfightidlebothanim;
443 if (weapons[weaponids[weaponactive]].getType() == sword)
444 return swordfightidleanim;
445 if (weapons[weaponids[weaponactive]].getType() == staff)
446 return swordfightidleanim;
448 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
449 return fightsidestep;
451 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
453 if (howactive == typesitting) return sitanim;
454 if (howactive == typesittingwall) return sitwallanim;
455 if (howactive == typesleeping) return sleepanim;
456 if (howactive == typedead1) return dead1anim;
457 if (howactive == typedead2) return dead2anim;
458 if (howactive == typedead3) return dead3anim;
459 if (howactive == typedead4) return dead4anim;
460 if (creature == rabbittype) return bounceidleanim;
461 if (creature == wolftype) return wolfidle;
466 * crouch animation for this creature
468 int Person::getCrouch()
470 if (creature == rabbittype)
472 if (creature == wolftype)
473 return wolfcrouchanim;
478 * running animation for this creature (can be upright or all fours)
482 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
484 if (creature == wolftype && (!superruntoggle))
487 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
488 return rabbitrunninganim;
489 if (creature == wolftype && (superruntoggle))
490 return wolfrunninganim;
496 int Person::getStop()
498 if (creature == rabbittype)
500 if (creature == wolftype)
507 int Person::getLanding()
509 if (creature == rabbittype)
511 if (creature == wolftype)
518 int Person::getLandhard()
520 if (creature == rabbittype)
522 if (creature == wolftype)
523 return wolflandhardanim;
530 * Person::DoAnimations
533 SolidHitBonus(int playerid)
535 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
536 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
538 award_bonus(playerid, solidhit);
542 * spawns blood effects
544 void Person::DoBlood(float howmuch, int which)
546 // FIXME: should abstract out inputs
547 static int bleedxint, bleedyint;
549 if (bloodtoggle && tutoriallevel != 1) {
550 if (bleeding <= 0 && spurt) {
552 for (int i = 0; i < 3; i++) {
553 // emit blood particles
556 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
557 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
558 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
559 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
562 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
563 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
564 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
565 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
568 if (Random() % 2 == 0) // 50% chance
569 for (int i = 0; i < 3; i++) {
570 if (Random() % 2 != 0) {
571 // emit teeth particles
574 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
575 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
578 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
579 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
583 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
585 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
587 Sprite::setLastSpriteSpecial(3); // sets it to teeth
592 // FIXME: manipulating attributes
593 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
596 if (creature == rabbittype)
597 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) {
598 bleedxint = abs(Random() % 512);
599 bleedyint = abs(Random() % 512);
601 if (creature == wolftype)
602 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) {
603 bleedxint = abs(Random() % 512);
604 bleedyint = abs(Random() % 512);
608 bleedy /= realtexdetail;
609 bleedx /= realtexdetail;
610 direction = abs(Random() % 2) * 2 - 1;
619 * spawns big blood effects and ???
620 * modifies character's skin texture
622 void Person::DoBloodBig(float howmuch, int which)
624 static int bleedxint, bleedyint, i, j;
626 if (howmuch && id == 0)
629 if (tutoriallevel != 1 || id == 0)
630 if (aitype != playercontrolled && howmuch > 0) {
634 // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
635 if (creature == wolftype) {
636 int i = abs(Random() % 2);
638 whichsound = snarlsound;
640 whichsound = snarl2sound;
641 envsound[numenvsounds] = coords;
642 envsoundvol[numenvsounds] = 16;
643 envsoundlife[numenvsounds] = .4;
646 if (creature == rabbittype) {
647 int i = abs(Random() % 2);
649 whichsound = rabbitpainsound;
650 if (i == 1 && howmuch >= 2)
651 whichsound = rabbitpain1sound;
652 envsound[numenvsounds] = coords;
653 envsoundvol[numenvsounds] = 16;
654 envsoundlife[numenvsounds] = .4;
658 if (whichsound != -1)
659 emit_sound_at(whichsound, coords);
662 if (id == 0 && howmuch > 0) {
663 // FIXME: manipulating attributes
671 if (bloodtoggle && decals && tutoriallevel != 1) {
672 if (bleeding <= 0 && spurt) {
674 for (int i = 0; i < 3; i++) {
675 // emit blood particles
676 // FIXME: copypaste from above
679 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
680 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
681 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
682 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
685 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
686 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
687 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
688 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
693 // weird texture manipulation code follows.
694 // looks like this is painting blood onto the character's skin texture
695 // FIXME: surely there's a better way
697 int offsetx = 0, offsety = 0;
699 offsety = Random() % 40;
700 offsetx = abs(Random() % 60);
702 if (which == 190 || which == 185) {
703 offsety = Random() % 40;
704 offsetx = abs(Random() % 100) - 20;
707 offsety = Random() % 10;
708 offsetx = Random() % 10;
711 offsety = Random() % 20;
712 offsetx = Random() % 20;
714 if (which == 220 || which == 215) {
724 if (creature == rabbittype)
725 for (i = 0; i < 512; i++) {
726 for (j = 0; j < 512; j++) {
727 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
728 if (i < startx) startx = i;
729 if (j < starty) starty = j;
730 if (i > endx) endx = i;
731 if (j > endy) endy = j;
735 if (creature == wolftype)
736 for (i = 0; i < 512; i++) {
737 for (j = 0; j < 512; j++) {
738 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
739 if (i < startx) startx = i;
740 if (j < starty) starty = j;
741 if (i > endx) endx = i;
742 if (j > endy) endy = j;
752 if (startx < 0) startx = 0;
753 if (starty < 0) starty = 0;
754 if (endx > 512 - 1) endx = 512 - 1;
755 if (endy > 512 - 1) endy = 512 - 1;
756 if (endx < startx) endx = startx;
757 if (endy < starty) endy = starty;
759 startx /= realtexdetail;
760 starty /= realtexdetail;
761 endx /= realtexdetail;
762 endy /= realtexdetail;
764 int texdetailint = realtexdetail;
766 if (creature == rabbittype)
767 for (i = startx; i < endx; i++) {
768 for (j = starty; j < endy; j++) {
769 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) {
770 color = Random() % 85 + 170;
771 where = i * skeleton.skinsize * 3 + j * 3;
772 if (skeleton.skinText[where + 0] > color / 2)
773 skeleton.skinText[where + 0] = color / 2;
774 skeleton.skinText[where + 1] = 0;
775 skeleton.skinText[where + 2] = 0;
779 if (creature == wolftype)
780 for (i = startx; i < endx; i++) {
781 for (j = starty; j < endy; j++) {
782 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) {
783 color = Random() % 85 + 170;
784 where = i * skeleton.skinsize * 3 + j * 3;
785 if (skeleton.skinText[where + 0] > color / 2)
786 skeleton.skinText[where + 0] = color / 2;
787 skeleton.skinText[where + 1] = 0;
788 skeleton.skinText[where + 2] = 0;
792 skeleton.drawmodel.textureptr.bind();
797 if (creature == rabbittype)
798 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) {
799 bleedxint = abs(Random() % 512);
800 bleedyint = abs(Random() % 512);
802 if (creature == wolftype)
803 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) {
804 bleedxint = abs(Random() % 512);
805 bleedyint = abs(Random() % 512);
807 bleedy = bleedxint + offsetx;
808 bleedx = bleedyint + offsety;
809 bleedy /= realtexdetail;
810 bleedx /= realtexdetail;
815 if (bleedx > skeleton.skinsize - 1)
816 bleedx = skeleton.skinsize - 1;
817 if (bleedy > skeleton.skinsize - 1)
818 bleedy = skeleton.skinsize - 1;
819 direction = abs(Random() % 2) * 2 - 1;
822 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
823 deathbleeding += bleeding;
824 bloodloss += bleeding * 3;
826 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
827 if (abs(Random() % 2) == 0) {
828 aitype = gethelptype;
831 aitype = attacktypecutoff;
839 * similar to DoBloodBig
841 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
845 static XYZ startpoint, endpoint, colpoint, movepoint;
846 static float rotationpoint;
848 static XYZ p1, p2, p3, p0;
851 float coordsx, coordsy;
854 if (bloodtoggle && decals && tutoriallevel != 1) {
857 where = DoRotation(where, 0, -yaw, 0);
865 // ray testing for a tri in the character model
866 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
867 if (whichtri != -1) {
868 // low level geometry math
870 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
871 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
872 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
874 bary.x = distsq(&p0, &p1);
875 bary.y = distsq(&p0, &p2);
876 bary.z = distsq(&p0, &p3);
878 total = bary.x + bary.y + bary.z;
887 total = bary.x + bary.y + bary.z;
893 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
894 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
895 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
896 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
897 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
898 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
899 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;
900 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;
902 if (bleeding <= 0 && spurt) {
904 for (int i = 0; i < 3; i++) {
905 // emit blood particles
906 // FIXME: more copypaste code
909 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
910 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
911 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
912 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
915 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
916 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
917 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
918 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
923 // texture manipulation follows
925 int offsetx = 0, offsety = 0;
926 offsetx = (1 + coordsy) * 512 - 291;
927 offsety = coordsx * 512 - 437;
934 if (creature == rabbittype)
935 for (i = 0; i < 512; i++) {
936 for (j = 0; j < 512; j++) {
937 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
938 if (i < startx) startx = i;
939 if (j < starty) starty = j;
940 if (i > endx) endx = i;
941 if (j > endy) endy = j;
945 if (creature == wolftype)
946 for (i = 0; i < 512; i++) {
947 for (j = 0; j < 512; j++) {
948 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
949 if (i < startx) startx = i;
950 if (j < starty) starty = j;
951 if (i > endx) endx = i;
952 if (j > endy) endy = j;
961 if (startx < 0) startx = 0;
962 if (starty < 0) starty = 0;
963 if (endx > 512 - 1) endx = 512 - 1;
964 if (endy > 512 - 1) endy = 512 - 1;
965 if (endx < startx) endx = startx;
966 if (endy < starty) endy = starty;
968 startx /= realtexdetail;
969 starty /= realtexdetail;
970 endx /= realtexdetail;
971 endy /= realtexdetail;
973 int texdetailint = realtexdetail;
975 if (creature == rabbittype)
976 for (i = startx; i < endx; i++) {
977 for (j = starty; j < endy; j++) {
978 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) {
979 color = Random() % 85 + 170;
980 where = i * skeleton.skinsize * 3 + j * 3;
981 if (skeleton.skinText[where + 0] > color / 2)
982 skeleton.skinText[where + 0] = color / 2;
983 skeleton.skinText[where + 1] = 0;
984 skeleton.skinText[where + 2] = 0;
985 } 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) {
986 color = Random() % 85 + 170;
987 where = i * skeleton.skinsize * 3 + j * 3;
988 if (skeleton.skinText[where + 0] > color / 2)
989 skeleton.skinText[where + 0] = color / 2;
990 skeleton.skinText[where + 1] = 0;
991 skeleton.skinText[where + 2] = 0;
995 if (creature == wolftype)
996 for (i = startx; i < endx; i++) {
997 for (j = starty; j < endy; j++) {
998 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) {
999 color = Random() % 85 + 170;
1000 where = i * skeleton.skinsize * 3 + j * 3;
1001 if (skeleton.skinText[where + 0] > color / 2)
1002 skeleton.skinText[where + 0] = color / 2;
1003 skeleton.skinText[where + 1] = 0;
1004 skeleton.skinText[where + 2] = 0;
1005 } 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) {
1006 color = Random() % 85 + 170;
1007 where = i * skeleton.skinsize * 3 + j * 3;
1008 if (skeleton.skinText[where + 0] > color / 2)
1009 skeleton.skinText[where + 0] = color / 2;
1010 skeleton.skinText[where + 1] = 0;
1011 skeleton.skinText[where + 2] = 0;
1015 skeleton.drawmodel.textureptr.bind();
1018 bleedy = (1 + coordsy) * 512;
1019 bleedx = coordsx * 512;
1020 bleedy /= realtexdetail;
1021 bleedx /= realtexdetail;
1026 if (bleedx > skeleton.skinsize - 1)
1027 bleedx = skeleton.skinsize - 1;
1028 if (bleedy > skeleton.skinsize - 1)
1029 bleedy = skeleton.skinsize - 1;
1030 direction = abs(Random() % 2) * 2 - 1;
1035 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1036 deathbleeding += bleeding;
1037 bloodloss += bleeding * 3;
1039 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1040 if (abs(Random() % 2) == 0) {
1041 aitype = gethelptype;
1044 aitype = attacktypecutoff;
1055 * guessing this performs a reversal
1057 void Person::Reverse()
1059 if (!((victim->aitype == playercontrolled
1061 || staggerdelay <= 0)
1062 && victim->animTarget != jumpupanim
1063 && victim->animTarget != jumpdownanim
1064 && (tutoriallevel != 1 || cananger)
1068 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1069 && (victim->id != 0 || difficulty >= 2)
1070 && (creature != wolftype || victim->creature == wolftype))
1073 if (animTarget == sweepanim) {
1074 animTarget = sweepreversedanim;
1075 animCurrent = sweepreversedanim;
1076 victim->animCurrent = sweepreversalanim;
1077 victim->animTarget = sweepreversalanim;
1079 if (animTarget == spinkickanim) {
1080 animTarget = spinkickreversedanim;
1081 animCurrent = spinkickreversedanim;
1082 victim->animCurrent = spinkickreversalanim;
1083 victim->animTarget = spinkickreversalanim;
1085 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1086 if (animTarget == rabbittacklinganim) {
1089 victim->frameCurrent = 6;
1090 victim->frameTarget = 7;
1092 animTarget = upunchreversedanim;
1093 animCurrent = upunchreversedanim;
1094 victim->animCurrent = upunchreversalanim;
1095 victim->animTarget = upunchreversalanim;
1097 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1098 if (victim->weaponactive != -1) {
1099 victim->throwtogglekeydown = 1;
1100 XYZ tempVelocity = victim->velocity * .2;
1101 if (tempVelocity.x == 0)
1102 tempVelocity.x = .1;
1103 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1104 victim->num_weapons--;
1105 if (victim->num_weapons) {
1106 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1107 if (victim->weaponstuck == victim->num_weapons)
1108 victim->weaponstuck = 0;
1111 victim->weaponactive = -1;
1112 for (unsigned j = 0; j < Person::players.size(); j++) {
1113 Person::players[j]->wentforweapon = 0;
1117 animTarget = staffhitreversedanim;
1118 animCurrent = staffhitreversedanim;
1119 victim->animCurrent = staffhitreversalanim;
1120 victim->animTarget = staffhitreversalanim;
1122 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1123 if (victim->weaponactive != -1) {
1124 victim->throwtogglekeydown = 1;
1125 XYZ tempVelocity = victim->velocity * .2;
1126 if (tempVelocity.x == 0)
1127 tempVelocity.x = .1;
1128 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1129 victim->num_weapons--;
1130 if (victim->num_weapons) {
1131 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1132 if (victim->weaponstuck == victim->num_weapons)
1133 victim->weaponstuck = 0;
1136 victim->weaponactive = -1;
1137 for (unsigned j = 0; j < Person::players.size(); j++) {
1138 Person::players[j]->wentforweapon = 0;
1141 animTarget = staffspinhitreversedanim;
1142 animCurrent = staffspinhitreversedanim;
1143 victim->animCurrent = staffspinhitreversalanim;
1144 victim->animTarget = staffspinhitreversalanim;
1146 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1147 if (victim->weaponactive != -1) {
1148 victim->throwtogglekeydown = 1;
1149 XYZ tempVelocity = victim->velocity * .2;
1150 if (tempVelocity.x == 0)
1151 tempVelocity.x = .1;
1152 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1153 victim->num_weapons--;
1154 if (victim->num_weapons) {
1155 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1156 if (victim->weaponstuck == victim->num_weapons)
1157 victim->weaponstuck = 0;
1160 victim->weaponactive = -1;
1161 for (unsigned j = 0; j < Person::players.size(); j++) {
1162 Person::players[j]->wentforweapon = 0;
1165 animTarget = swordslashreversedanim;
1166 animCurrent = swordslashreversedanim;
1167 victim->animCurrent = swordslashreversalanim;
1168 victim->animTarget = swordslashreversalanim;
1170 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1171 if (victim->weaponactive != -1) {
1172 victim->throwtogglekeydown = 1;
1173 XYZ tempVelocity = victim->velocity * .2;
1174 if (tempVelocity.x == 0)
1175 tempVelocity.x = .1;
1176 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1177 victim->num_weapons--;
1178 if (victim->num_weapons) {
1179 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1180 if (victim->weaponstuck == victim->num_weapons)
1181 victim->weaponstuck = 0;
1184 victim->weaponactive = -1;
1185 for (unsigned j = 0; j < Person::players.size(); j++) {
1186 Person::players[j]->wentforweapon = 0;
1189 animTarget = knifeslashreversedanim;
1190 animCurrent = knifeslashreversedanim;
1191 victim->animCurrent = knifeslashreversalanim;
1192 victim->animTarget = knifeslashreversalanim;
1194 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1195 victim->targettilt2 = targettilt2;
1196 victim->frameCurrent = frameCurrent;
1197 victim->frameTarget = frameTarget;
1198 victim->target = target;
1199 victim->velocity = 0;
1200 victim->oldcoords = victim->coords;
1201 victim->coords = coords;
1202 victim->targetyaw = targetyaw;
1203 victim->yaw = targetyaw;
1204 victim->victim = this->shared_from_this();
1206 if (animTarget == winduppunchanim) {
1207 animTarget = winduppunchblockedanim;
1208 victim->animTarget = blockhighleftanim;
1209 victim->frameTarget = 1;
1210 victim->target = .5;
1211 victim->victim = this->shared_from_this();
1212 victim->targetyaw = targetyaw + 180;
1214 if (animTarget == wolfslapanim) {
1215 animTarget = winduppunchblockedanim;
1216 victim->animTarget = blockhighleftanim;
1217 victim->frameTarget = 1;
1218 victim->target = .5;
1219 victim->victim = this->shared_from_this();
1220 victim->targetyaw = targetyaw + 180;
1222 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1223 animTarget = swordslashparriedanim;
1224 parriedrecently = .4;
1225 victim->parriedrecently = 0;
1226 victim->animTarget = swordslashparryanim;
1227 victim->frameTarget = 1;
1228 victim->target = .5;
1229 victim->victim = this->shared_from_this();
1230 victim->targetyaw = targetyaw + 180;
1232 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1233 if (victim->weaponactive != -1) {
1234 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1235 if (weapons[victim->weaponids[0]].getType() == staff)
1236 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1237 if (weapons[weaponids[0]].getType() == staff)
1238 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1239 emit_sound_at(swordstaffsound, victim->coords);
1241 emit_sound_at(metalhitsound, victim->coords);
1245 victim->Puff(righthand);
1247 victim->frameTarget = 0;
1248 victim->animTarget = staggerbackhighanim;
1249 victim->targetyaw = targetyaw + 180;
1251 aim = DoRotation(facing, 0, 90, 0) * 21;
1253 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1254 victim->num_weapons--;
1255 if (victim->num_weapons) {
1256 victim->weaponids[0] = victim->weaponids[num_weapons];
1257 if (victim->weaponstuck == victim->num_weapons)
1258 victim->weaponstuck = 0;
1260 victim->weaponactive = -1;
1261 for (unsigned i = 0; i < Person::players.size(); i++) {
1262 Person::players[i]->wentforweapon = 0;
1266 if (abs(Random() % 20) == 0) {
1267 if (weaponactive != -1) {
1268 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1269 if (weapons[victim->weaponids[0]].getType() == staff)
1270 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1271 if (weapons[weaponids[0]].getType() == staff)
1272 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1274 emit_sound_at(swordstaffsound, coords);
1276 emit_sound_at(metalhitsound, coords);
1284 animTarget = staggerbackhighanim;
1285 targetyaw = targetyaw + 180;
1287 aim = DoRotation(facing, 0, 90, 0) * 21;
1289 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1292 weaponids[0] = weaponids[num_weapons];
1293 if (weaponstuck == num_weapons)
1297 for (unsigned i = 0; i < Person::players.size(); i++) {
1298 Person::players[i]->wentforweapon = 0;
1305 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1306 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1307 victim->animTarget = dodgebackanim;
1308 victim->frameTarget = 0;
1312 rotatetarget = coords - victim->coords;
1313 Normalise(&rotatetarget);
1314 victim->targetyaw = -asin(0 - rotatetarget.x);
1315 victim->targetyaw *= 360 / 6.28;
1316 if (rotatetarget.z < 0)
1317 victim->targetyaw = 180 - victim->targetyaw;
1319 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1321 victim->lastattack3 = victim->lastattack2;
1322 victim->lastattack2 = victim->lastattack;
1323 victim->lastattack = victim->animTarget;
1325 victim->animTarget = sweepanim;
1326 victim->frameTarget = 0;
1330 rotatetarget = coords - victim->coords;
1331 Normalise(&rotatetarget);
1332 victim->targetyaw = -asin(0 - rotatetarget.x);
1333 victim->targetyaw *= 360 / 6.28;
1334 if (rotatetarget.z < 0)
1335 victim->targetyaw = 180 - victim->targetyaw;
1337 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1339 victim->lastattack3 = victim->lastattack2;
1340 victim->lastattack2 = victim->lastattack;
1341 victim->lastattack = victim->animTarget;
1346 victim->velocity = 0;
1348 if (aitype != playercontrolled)
1350 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1352 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1354 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1357 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1364 void Person::DoDamage(float howmuch)
1366 // subtract health (temporary?)
1367 if (tutoriallevel != 1)
1368 damage += howmuch / power;
1371 damagedealt += howmuch / power;
1373 damagetaken += howmuch / power;
1376 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1379 if (tutoriallevel != 1)
1380 permanentdamage += howmuch / 2 / power;
1381 if (tutoriallevel != 1)
1382 superpermanentdamage += howmuch / 4 / power;
1384 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1386 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1390 camerashake += howmuch / 100;
1391 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1392 blackout = damage / damagetolerance;
1397 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1398 aitype = attacktypecutoff;
1399 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1400 if (abs(Random() % 2) == 0) {
1401 aitype = gethelptype;
1404 aitype = attacktypecutoff;
1408 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1411 for (int i = 0; i < skeleton.num_joints; i++) {
1412 if (skeleton.free) {
1413 flatvelocity2 = skeleton.joints[i].velocity;
1414 flatfacing2 = skeleton.joints[i].position * scale + coords;
1416 flatvelocity2 = velocity;
1417 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1419 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1420 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1421 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1422 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1423 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1424 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1427 emit_sound_at(splattersound, coords);
1432 if (!dead && creature == wolftype) {
1433 award_bonus(0, Wolfbonus);
1440 if (tutoriallevel != 1 || id == 0)
1441 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1442 int whichsound = -1;
1444 if (creature == wolftype) {
1445 int i = abs(Random() % 2);
1447 whichsound = snarlsound;
1449 whichsound = snarl2sound;
1450 envsound[numenvsounds] = coords;
1451 envsoundvol[numenvsounds] = 16;
1452 envsoundlife[numenvsounds] = .4;
1455 if (creature == rabbittype) {
1456 int i = abs(Random() % 2);
1458 whichsound = rabbitpainsound;
1459 if (i == 1 && damage > damagetolerance)
1460 whichsound = rabbitpain1sound;
1461 envsound[numenvsounds] = coords;
1462 envsoundvol[numenvsounds] = 16;
1463 envsoundlife[numenvsounds] = .4;
1467 if (whichsound != -1) {
1468 emit_sound_at(whichsound, coords);
1475 * calculate/animate head facing direction?
1477 void Person::DoHead()
1479 static XYZ rotatearound;
1481 static float lookspeed = 500;
1483 if (!freeze && !winfreeze) {
1486 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1487 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1489 while (targetheadyaw > 180)targetheadyaw -= 360;
1490 while (targetheadyaw < -180)targetheadyaw += 360;
1492 if (targetheadyaw > 160)
1493 targetheadpitch = targetheadpitch * -1;
1494 if (targetheadyaw < -160)
1495 targetheadpitch = targetheadpitch * -1;
1496 if (targetheadyaw > 160)
1497 targetheadyaw = targetheadyaw - 180;
1498 if (targetheadyaw < -160)
1499 targetheadyaw = targetheadyaw + 180;
1501 if (targetheadpitch > 120)
1502 targetheadpitch = 120;
1503 if (targetheadpitch < -120)
1504 targetheadpitch = -120;
1505 if (targetheadyaw > 120)
1506 targetheadyaw = 120;
1507 if (targetheadyaw < -120)
1508 targetheadyaw = -120;
1511 targetheadpitch = 0;
1513 if (targetheadyaw > 80)
1515 if (targetheadyaw < -80)
1516 targetheadyaw = -80;
1517 if (targetheadpitch > 50)
1518 targetheadpitch = 50;
1519 if (targetheadpitch < -50)
1520 targetheadpitch = -50;
1523 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1524 headyaw = targetheadyaw;
1525 else if (headyaw > targetheadyaw) {
1526 headyaw -= multiplier * lookspeed;
1527 } else if (headyaw < targetheadyaw) {
1528 headyaw += multiplier * lookspeed;
1531 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1532 headpitch = targetheadpitch;
1533 else if (headpitch > targetheadpitch) {
1534 headpitch -= multiplier * lookspeed / 2;
1535 } else if (headpitch < targetheadpitch) {
1536 headpitch += multiplier * lookspeed / 2;
1539 rotatearound = jointPos(neck);
1540 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1544 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1545 facing = DoRotation(facing, headpitch * .4, 0, 0);
1546 facing = DoRotation(facing, 0, headyaw * .4, 0);
1549 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1550 facing = DoRotation(facing, headpitch * .8, 0, 0);
1551 facing = DoRotation(facing, 0, headyaw * .8, 0);
1554 if (animTarget == walkanim) {
1555 facing = DoRotation(facing, headpitch * .6, 0, 0);
1556 facing = DoRotation(facing, 0, headyaw * .6, 0);
1559 skeleton.specialforward[0] = facing;
1560 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1561 for (int i = 0; i < skeleton.num_muscles; i++) {
1562 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1563 skeleton.FindRotationMuscle(i, animTarget);
1570 * ragdolls character?
1572 void Person::RagDoll(bool checkcollision)
1577 if (!skeleton.free) {
1580 if (id == 0 && isFlip())
1587 facing = DoRotation(facing, 0, yaw, 0);
1589 skeleton.freetime = 0;
1591 skeleton.longdead = 0;
1594 skeleton.broken = 0;
1595 skeleton.spinny = 1;
1597 skeleton.freefall = 1;
1599 if (!isnormal(velocity.x)) velocity.x = 0;
1600 if (!isnormal(velocity.y)) velocity.y = 0;
1601 if (!isnormal(velocity.z)) velocity.z = 0;
1602 if (!isnormal(yaw)) yaw = 0;
1603 if (!isnormal(coords.x)) coords = 0;
1604 if (!isnormal(tilt)) tilt = 0;
1605 if (!isnormal(tilt2)) tilt2 = 0;
1607 for (int i = 0; i < skeleton.num_joints; i++) {
1608 skeleton.joints[i].delay = 0;
1609 skeleton.joints[i].locked = 0;
1610 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1611 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1612 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1613 skeleton.joints[i].position.y += .1;
1614 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1615 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1618 for (int i = 0; i < skeleton.num_joints; i++) {
1619 skeleton.joints[i].velocity = 0;
1620 skeleton.joints[i].velchange = 0;
1622 skeleton.DoConstraints(&coords, &scale);
1623 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1624 skeleton.DoConstraints(&coords, &scale);
1625 skeleton.DoConstraints(&coords, &scale);
1626 skeleton.DoConstraints(&coords, &scale);
1627 skeleton.DoConstraints(&coords, &scale);
1630 speed = animation[animTarget].speed[frameTarget] * 2;
1631 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1632 speed = animation[animCurrent].speed[frameCurrent] * 2;
1635 speed = transspeed * 2;
1639 for (int i = 0; i < skeleton.num_joints; i++) {
1640 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1641 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);
1643 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1644 change.x = (float)(Random() % 100) / 100;
1645 change.y = (float)(Random() % 100) / 100;
1646 change.z = (float)(Random() % 100) / 100;
1647 skeleton.joints[i].velocity += change;
1648 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1650 change.x = (float)(Random() % 100) / 100;
1651 change.y = (float)(Random() % 100) / 100;
1652 change.z = (float)(Random() % 100) / 100;
1653 skeleton.joints[i].velchange += change;
1654 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1657 if (checkcollision) {
1664 for (j = 0; j < skeleton.num_joints; j++) {
1665 average += skeleton.joints[j].position;
1669 coords += average * scale;
1670 for (j = 0; j < skeleton.num_joints; j++) {
1671 skeleton.joints[j].position -= average;
1674 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1675 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1676 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1677 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1678 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1681 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1682 coords.x = lowpoint.x;
1683 coords.z = lowpoint.z;
1692 for (int i = 0; i < skeleton.num_joints; i++) {
1693 velocity += skeleton.joints[i].velocity * scale;
1695 velocity /= skeleton.num_joints;
1698 if (Random() % 2 == 0) {
1699 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1700 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1701 weapons[weaponids[0]].velocity.x += .01;
1704 weaponids[0] = weaponids[num_weapons];
1705 if (weaponstuck == num_weapons)
1709 for (unsigned i = 0; i < Person::players.size(); i++) {
1710 Person::players[i]->wentforweapon = 0;
1715 animTarget = bounceidleanim;
1716 animCurrent = bounceidleanim;
1726 void Person::FootLand(int which, float opacity)
1728 static XYZ terrainlight;
1729 static XYZ footvel, footpoint;
1730 if (opacity >= 1 || skiddelay <= 0)
1734 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1736 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1737 //footpoint.y=coords.y;
1738 if (distsq(&footpoint, &viewer))
1739 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1740 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1741 footvel = velocity / 5;
1745 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1747 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1748 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1749 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1750 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1751 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1752 if (opacity >= 1 || detail == 2)
1754 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1755 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1756 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1757 footvel = velocity / 5;
1761 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1763 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1764 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1765 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1766 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1767 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1768 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1769 footvel = velocity / 5;
1773 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1775 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1776 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1777 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1778 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1779 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1780 if (opacity >= 1 || detail == 2)
1782 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1783 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1784 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1785 footvel = velocity / 5;
1789 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1791 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1792 //footpoint.y=coords.y;
1793 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1794 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1799 * make a puff effect at a body part (dust effect?)
1801 void Person::Puff(int whichlabel)
1803 static XYZ footvel, footpoint;
1806 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1807 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1811 * I think I added this in an attempt to clean up code
1813 void Person::setAnimation(int animation)
1815 animTarget = animation;
1824 void Person::DoAnimations()
1826 if (!skeleton.free) {
1827 static float oldtarget;
1829 if (isIdle() && animCurrent != getIdle())
1830 normalsupdatedelay = 0;
1832 if (animTarget == tempanim || animCurrent == tempanim) {
1833 animation[tempanim] = tempanimation;
1835 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1841 vel[0] = velocity.x;
1842 vel[1] = velocity.y;
1843 vel[2] = velocity.z;
1846 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1847 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1849 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1851 if (!crouchkeydown && velocity.y >= -15)
1854 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1859 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1861 if (normaldotproduct(targfacing, velocity) >= -.3)
1862 animTarget = flipanim;
1864 animTarget = backflipanim;
1865 crouchtogglekeydown = 1;
1873 if (animation[animTarget].attack != reversed)
1875 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1876 crouchtogglekeydown = 0;
1877 if (aitype == playercontrolled)
1880 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1883 crouchtogglekeydown = 1;
1887 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1889 normalsupdatedelay = 0;
1893 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1895 emit_sound_at(fireendsound, coords);
1896 pause_sound(stream_firesound);
1900 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1901 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1903 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1904 if (normaldotproduct(victim->facing, facing) > 0)
1905 victim->animTarget = rabbittackledbackanim;
1907 victim->animTarget = rabbittackledfrontanim;
1908 victim->frameTarget = 2;
1911 victim->targetyaw = yaw;
1912 if (victim->aitype == gethelptype)
1913 victim->DoDamage(victim->damagetolerance - victim->damage);
1914 //victim->DoDamage(30);
1915 if (creature == wolftype) {
1917 emit_sound_at(clawslicesound, victim->coords);
1919 victim->DoBloodBig(1 / victim->armorhead, 210);
1921 award_bonus(id, TackleBonus,
1922 victim->aitype == gethelptype ? 50 : 0);
1926 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1927 if (weapons[weaponids[0]].getType() == knife) {
1928 if (weaponactive == -1)
1930 else if (weaponactive == 0)
1933 if (weaponactive == -1) {
1934 emit_sound_at(knifesheathesound, coords);
1936 if (weaponactive != -1) {
1937 emit_sound_at(knifedrawsound, coords, 128);
1940 drawtogglekeydown = 1;
1943 if (tutoriallevel != 1 || id == 0)
1944 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1947 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1948 if (animation[animTarget].label[frameTarget] == 1)
1949 whichsound = footstepsound;
1951 whichsound = footstepsound2;
1952 if (animation[animTarget].label[frameTarget] == 1)
1954 if (animation[animTarget].label[frameTarget] == 2)
1956 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1962 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1963 if (animation[animTarget].label[frameTarget] == 1)
1964 whichsound = footstepsound3;
1966 whichsound = footstepsound4;
1970 if (animation[animTarget].label[frameTarget] == 1)
1971 whichsound = footstepsound3;
1973 whichsound = footstepsound4;
1975 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1976 if (animation[animTarget].attack != neutral) {
1977 unsigned r = abs(Random() % 3);
1979 whichsound = lowwhooshsound;
1981 whichsound = midwhooshsound;
1983 whichsound = highwhooshsound;
1985 if (animation[animTarget].attack == neutral)
1986 whichsound = movewhooshsound;
1987 } else if (animation[animTarget].label[frameTarget] == 4)
1988 whichsound = knifeswishsound;
1989 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1990 whichsound = landsound2;
1992 emit_sound_at(whichsound, coords, 256.);
1995 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1996 envsound[numenvsounds] = coords;
1997 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1998 envsoundvol[numenvsounds] = 15;
2000 envsoundvol[numenvsounds] = 6;
2001 envsoundlife[numenvsounds] = .4;
2005 if (animation[animTarget].label[frameTarget] == 3) {
2007 emit_sound_at(whichsound, coords, 128.);
2012 if (tutoriallevel != 1 || id == 0)
2013 if (speechdelay <= 0)
2014 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2015 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2016 int whichsound = -1;
2017 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2018 if (animation[animTarget].attack != neutral) {
2019 unsigned r = abs(Random() % 4);
2020 if (creature == rabbittype) {
2021 if (r == 0) whichsound = rabbitattacksound;
2022 if (r == 1) whichsound = rabbitattack2sound;
2023 if (r == 2) whichsound = rabbitattack3sound;
2024 if (r == 3) whichsound = rabbitattack4sound;
2026 if (creature == wolftype) {
2027 if (r == 0) whichsound = barksound;
2028 if (r == 1) whichsound = bark2sound;
2029 if (r == 2) whichsound = bark3sound;
2030 if (r == 3) whichsound = barkgrowlsound;
2036 if (whichsound != -1) {
2037 emit_sound_at(whichsound, coords);
2043 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2049 currentoffset = targetoffset;
2050 frameTarget = frameCurrent;
2051 animCurrent = animTarget;
2054 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2055 for (unsigned i = 0; i < weapons.size(); i++) {
2056 if (weapons[i].owner == -1)
2057 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2058 if (distsq(&coords, &weapons[i].position) >= 1) {
2059 if (weapons[i].getType() != staff) {
2060 emit_sound_at(knifedrawsound, coords, 128.);
2069 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2070 for (unsigned i = 0; i < weapons.size(); i++) {
2071 bool willwork = true;
2072 if (weapons[i].owner != -1)
2073 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2074 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2075 if (Person::players[weapons[i].owner]->num_weapons > 1)
2077 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2078 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2079 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2080 bool fleshstuck = false;
2081 if (weapons[i].owner != -1)
2082 if (victim->weaponstuck != -1) {
2083 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2088 emit_sound_at(fleshstabremovesound, coords, 128.);
2090 if (weapons[i].getType() != staff) {
2091 emit_sound_at(knifedrawsound, coords, 128.);
2094 if (weapons[i].owner != -1) {
2095 victim = Person::players[weapons[i].owner];
2096 if (victim->num_weapons == 1)
2097 victim->num_weapons = 0;
2099 victim->num_weapons = 1;
2101 //victim->weaponactive=-1;
2102 victim->skeleton.longdead = 0;
2103 victim->skeleton.free = 1;
2104 victim->skeleton.broken = 0;
2106 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2107 victim->skeleton.joints[j].velchange = 0;
2108 victim->skeleton.joints[j].locked = 0;
2114 Normalise(&relative);
2115 XYZ footvel, footpoint;
2117 footpoint = weapons[i].position;
2118 if (victim->weaponstuck != -1) {
2119 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2121 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2122 weapons[i].bloody = 2;
2123 weapons[i].blooddrip = 5;
2124 victim->weaponstuck = -1;
2127 if (victim->num_weapons > 0) {
2128 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2129 victim->weaponstuck = 0;
2130 if (victim->weaponids[0] == int(i))
2131 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2134 victim->jointVel(abdomen) += relative * 6;
2135 victim->jointVel(neck) += relative * 6;
2136 victim->jointVel(rightshoulder) += relative * 6;
2137 victim->jointVel(leftshoulder) += relative * 6;
2145 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2146 if (weaponactive == -1)
2148 else if (weaponactive == 0) {
2150 if (num_weapons == 2) {
2152 buffer = weaponids[0];
2153 weaponids[0] = weaponids[1];
2154 weaponids[1] = buffer;
2157 if (weaponactive == -1) {
2158 emit_sound_at(knifesheathesound, coords, 128.);
2160 if (weaponactive != -1) {
2161 emit_sound_at(knifedrawsound, coords, 128.);
2166 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2167 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2168 Normalise(&rotatetarget);
2169 targetyaw = -asin(0 - rotatetarget.x);
2170 targetyaw *= 360 / 6.28;
2171 if (rotatetarget.z < 0)
2172 targetyaw = 180 - targetyaw;
2174 if (animTarget == walljumprightkickanim)
2176 if (animTarget == walljumpleftkickanim)
2182 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2185 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2190 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2191 animTarget = rabbittackleanim;
2193 emit_sound_at(jumpsound, coords);
2201 targetloc = velocity;
2202 Normalise(&targetloc);
2203 targetloc += coords;
2204 for (unsigned i = 0; i < Person::players.size(); i++) {
2206 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2207 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2211 if (closestid != -1)
2212 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2214 victim = Person::players[closestid];
2215 coords = victim->coords;
2216 animCurrent = rabbittacklinganim;
2217 animTarget = rabbittacklinganim;
2221 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2222 rotatetarget = coords - victim->coords;
2223 Normalise(&rotatetarget);
2224 targetyaw = -asin(0 - rotatetarget.x);
2225 targetyaw *= 360 / 6.28;
2226 if (rotatetarget.z < 0)
2227 targetyaw = 180 - targetyaw;
2229 if (animTarget != rabbitrunninganim) {
2230 emit_sound_at(jumpsound, coords, 128.);
2236 float damagemult = 1 * power;
2237 if (creature == wolftype)
2238 damagemult = 2.5 * power;
2240 damagemult /= victim->damagetolerance / 200;
2242 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2243 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2244 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2248 if (Random() % 2 || creature == wolftype) {
2251 if (creature == wolftype)
2254 if (tutoriallevel != 1) {
2255 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2257 if (creature == wolftype) {
2258 emit_sound_at(clawslicesound, victim->coords, 128.);
2260 victim->DoBloodBig(2 / victim->armorhead, 175);
2264 relative = victim->coords - coords;
2266 Normalise(&relative);
2267 relative = DoRotation(relative, 0, -90, 0);
2268 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2269 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2271 victim->jointVel(head) += relative * damagemult * 200;
2274 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2280 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2281 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2285 if (Random() % 2 || creature == wolftype) {
2287 if (creature == wolftype)
2290 emit_sound_at(whooshhitsound, victim->coords);
2291 if (creature == wolftype) {
2292 emit_sound_at(clawslicesound, victim->coords, 128.);
2294 victim->DoBloodBig(2, 175);
2298 relative = victim->coords - coords;
2300 Normalise(&relative);
2302 Normalise(&relative);
2303 relative = DoRotation(relative, 0, 90, 0);
2304 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2305 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2307 victim->jointVel(head) += relative * damagemult * 100;
2310 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2314 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2315 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2321 if (tutoriallevel != 1) {
2322 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2324 if (creature == wolftype) {
2325 emit_sound_at(clawslicesound, victim->coords, 128.);
2327 victim->DoBloodBig(2 / victim->armorhead, 175);
2333 Normalise(&relative);
2334 relative = DoRotation(relative, 0, -90, 0);
2335 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2336 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2338 victim->jointVel(head) += relative * damagemult * 200;
2341 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2343 if (victim->damage > victim->damagetolerance)
2344 award_bonus(id, style);
2350 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2351 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2357 if (tutoriallevel != 1) {
2358 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2360 if (creature == wolftype) {
2361 emit_sound_at(clawslicesound, victim->coords, 128.);
2363 victim->DoBloodBig(2 / victim->armorhead, 175);
2369 Normalise(&relative);
2370 relative = DoRotation(relative, 0, 90, 0);
2371 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2372 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2374 victim->jointVel(head) += relative * damagemult * 200;
2377 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2379 if (victim->damage > victim->damagetolerance)
2380 award_bonus(id, style);
2386 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2387 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2395 emit_sound_at(whooshhitsound, victim->coords);
2398 relative = victim->coords - coords;
2400 Normalise(&relative);
2401 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2402 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2404 victim->jointVel(head) += relative * damagemult * 100;
2407 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2411 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2412 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2416 emit_sound_at(whooshhitsound, victim->coords, 128.);
2418 victim->skeleton.longdead = 0;
2419 victim->skeleton.free = 1;
2420 victim->skeleton.broken = 0;
2421 victim->skeleton.spinny = 1;
2423 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2424 victim->skeleton.joints[i].velchange = 0;
2425 victim->skeleton.joints[i].delay = 0;
2426 victim->skeleton.joints[i].locked = 0;
2427 //victim->skeleton.joints[i].velocity=0;
2433 Normalise(&relative);
2434 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2435 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2436 victim->skeleton.joints[i].position.y += relative.y * .3;
2437 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2438 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2440 victim->Puff(abdomen);
2441 victim->jointVel(abdomen).y = relative.y * 400;
2445 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2446 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2450 if (tutoriallevel != 1) {
2451 emit_sound_at(heavyimpactsound, coords, 128.);
2454 relative = victim->coords - coords;
2456 Normalise(&relative);
2457 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2458 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2460 victim->Puff(abdomen);
2461 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2465 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2466 victim->jointVel(abdomen) += relative * damagemult * 300;
2470 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2471 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2475 if (tutoriallevel != 1) {
2476 emit_sound_at(thudsound, coords);
2479 victim->skeleton.longdead = 0;
2480 victim->skeleton.free = 1;
2481 victim->skeleton.broken = 0;
2482 victim->skeleton.spinny = 1;
2484 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2485 victim->skeleton.joints[i].velchange = 0;
2486 //victim->skeleton.joints[i].delay=0;
2487 victim->skeleton.joints[i].locked = 0;
2490 relative = victim->coords - coords;
2491 Normalise(&relative);
2493 Normalise(&relative);
2494 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2495 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2500 victim->Puff(abdomen);
2501 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2502 victim->jointVel(abdomen) += relative * damagemult * 200;
2511 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2514 if (!victim->skeleton.free)
2518 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2519 emit_sound_at(knifesheathesound, coords, 128.);
2522 if (victim && hasvictim) {
2523 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2525 XYZ where, startpoint, endpoint, movepoint, colpoint;
2526 float rotationpoint;
2528 if (weapons[weaponids[weaponactive]].getType() == knife) {
2529 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2530 where -= victim->coords;
2531 if (!victim->skeleton.free)
2532 where = DoRotation(where, 0, -victim->yaw, 0);
2535 startpoint.y += 100;
2539 if (weapons[weaponids[weaponactive]].getType() == sword) {
2540 where = weapons[weaponids[weaponactive]].position;
2541 where -= victim->coords;
2542 if (!victim->skeleton.free)
2543 where = DoRotation(where, 0, -victim->yaw, 0);
2545 where = weapons[weaponids[weaponactive]].tippoint;
2546 where -= victim->coords;
2547 if (!victim->skeleton.free)
2548 where = DoRotation(where, 0, -victim->yaw, 0);
2551 if (weapons[weaponids[weaponactive]].getType() == staff) {
2552 where = weapons[weaponids[weaponactive]].position;
2553 where -= victim->coords;
2554 if (!victim->skeleton.free)
2555 where = DoRotation(where, 0, -victim->yaw, 0);
2557 where = weapons[weaponids[weaponactive]].tippoint;
2558 where -= victim->coords;
2559 if (!victim->skeleton.free)
2560 where = DoRotation(where, 0, -victim->yaw, 0);
2565 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2567 if (whichtri != -1) {
2568 if (victim->dead != 2) {
2569 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2571 award_bonus(id, FinishedBonus);
2574 weapons[weaponids[weaponactive]].bloody = 2;
2576 victim->skeleton.longdead = 0;
2577 victim->skeleton.free = 1;
2578 victim->skeleton.broken = 0;
2580 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2581 victim->skeleton.joints[i].velchange = 0;
2582 victim->skeleton.joints[i].locked = 0;
2583 //victim->skeleton.joints[i].velocity=0;
2585 emit_sound_at(fleshstabsound, coords, 128);
2588 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2589 weapons[weaponids[weaponactive]].blooddrip += 5;
2590 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2592 if (whichtri == -1) {
2594 emit_sound_at(knifesheathesound, coords, 128.);
2600 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2602 emit_sound_at(knifedrawsound, coords, 128);
2605 if (victim && hasvictim) {
2606 XYZ footvel, footpoint;
2608 emit_sound_at(fleshstabremovesound, coords, 128.);
2611 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2613 if (weapons[weaponids[weaponactive]].getType() == sword) {
2614 XYZ where, startpoint, endpoint, movepoint;
2615 float rotationpoint;
2618 where = weapons[weaponids[weaponactive]].position;
2619 where -= victim->coords;
2620 if (!victim->skeleton.free)
2621 where = DoRotation(where, 0, -victim->yaw, 0);
2623 where = weapons[weaponids[weaponactive]].tippoint;
2624 where -= victim->coords;
2625 if (!victim->skeleton.free)
2626 where = DoRotation(where, 0, -victim->yaw, 0);
2631 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2632 footpoint += victim->coords;
2634 if (whichtri == -1) {
2635 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2638 if (weapons[weaponids[weaponactive]].getType() == staff) {
2639 XYZ where, startpoint, endpoint, movepoint;
2640 float rotationpoint;
2643 where = weapons[weaponids[weaponactive]].position;
2644 where -= victim->coords;
2645 if (!victim->skeleton.free)
2646 where = DoRotation(where, 0, -victim->yaw, 0);
2648 where = weapons[weaponids[weaponactive]].tippoint;
2649 where -= victim->coords;
2650 if (!victim->skeleton.free)
2651 where = DoRotation(where, 0, -victim->yaw, 0);
2656 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2657 footpoint += victim->coords;
2659 if (whichtri == -1) {
2660 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2663 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2665 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2666 victim->skeleton.longdead = 0;
2667 victim->skeleton.free = 1;
2668 victim->skeleton.broken = 0;
2670 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2671 victim->skeleton.joints[i].velchange = 0;
2672 victim->skeleton.joints[i].locked = 0;
2673 //victim->skeleton.joints[i].velocity=0;
2679 Normalise(&relative);
2680 //victim->Puff(abdomen);
2682 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2684 if (victim->bloodloss < victim->damagetolerance) {
2685 victim->bloodloss += 1000;
2689 victim->jointVel(abdomen) += relative * damagemult * 20;
2693 if (!hasvictim && onterrain) {
2694 weapons[weaponids[weaponactive]].bloody = 0;
2695 weapons[weaponids[weaponactive]].blooddrip = 0;
2699 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2700 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2708 if (tutoriallevel != 1) {
2709 emit_sound_at(heavyimpactsound, victim->coords, 128);
2714 relative = victim->coords - coords;
2716 Normalise(&relative);
2717 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2718 victim->skeleton.joints[i].velocity = relative * 30;
2720 victim->jointVel(head) += relative * damagemult * 150;
2722 victim->frameTarget = 0;
2723 victim->animTarget = staggerbackhardanim;
2724 victim->targetyaw = targetyaw + 180;
2726 victim->stunned = 1;
2729 victim->Puff(abdomen);
2730 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2737 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2738 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2742 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2743 if (tutoriallevel != 1) {
2744 emit_sound_at(thudsound, victim->coords);
2746 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2747 if (tutoriallevel != 1) {
2748 emit_sound_at(whooshhitsound, victim->coords);
2751 if (tutoriallevel != 1) {
2752 emit_sound_at(heavyimpactsound, victim->coords);
2756 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2759 relative = victim->coords - coords;
2761 Normalise(&relative);
2763 Normalise(&relative);
2764 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2765 victim->skeleton.joints[i].velocity = relative * 5;
2767 victim->jointVel(abdomen) += relative * damagemult * 400;
2769 victim->frameTarget = 0;
2770 victim->animTarget = staggerbackhardanim;
2771 victim->targetyaw = targetyaw + 180;
2773 victim->stunned = 1;
2775 victim->Puff(abdomen);
2776 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2782 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2783 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2784 if (victim->id == 0)
2786 emit_sound_at(landsound2, victim->coords);
2792 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2793 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2794 if (victim->id == 0)
2797 if (weaponactive != -1) {
2798 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2799 if (weapons[victim->weaponids[0]].getType() == staff)
2800 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2801 if (weapons[weaponids[0]].getType() == staff)
2802 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2804 emit_sound_at(swordstaffsound, victim->coords);
2806 emit_sound_at(metalhitsound, victim->coords);
2814 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2815 if (weaponactive != -1) {
2818 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);
2820 weapons[weaponids[0]].thrown(aim * 50);
2823 weaponids[0] = weaponids[num_weapons];
2829 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2831 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2833 if (tutoriallevel != 1)
2834 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2836 award_bonus(id, Slicebonus);
2837 if (tutoriallevel != 1) {
2838 emit_sound_at(knifeslicesound, victim->coords);
2840 //victim->jointVel(abdomen)+=relative*damagemult*200;
2841 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2842 if (victim->id != 0 || difficulty == 2) {
2843 victim->frameTarget = 0;
2844 victim->animTarget = staggerbackhardanim;
2845 victim->targetyaw = targetyaw + 180;
2849 victim->lowreversaldelay = 0;
2850 victim->highreversaldelay = 0;
2851 if (aitype != playercontrolled)
2852 weaponmissdelay = .6;
2854 if (tutoriallevel != 1)
2855 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2856 weapons[weaponids[weaponactive]].bloody = 1;
2857 if (tutoriallevel != 1)
2858 weapons[weaponids[weaponactive]].blooddrip += 3;
2860 XYZ footvel, footpoint;
2862 if (skeleton.free) {
2863 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2865 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2867 if (tutoriallevel != 1) {
2869 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2870 footvel = DoRotation(facing, 0, 90, 0) * .8;
2872 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2873 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2874 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2875 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2877 if (tutoriallevel == 1) {
2878 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2880 victim->DoDamage(damagemult * 0);
2883 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2884 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2885 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2886 award_bonus(id, Slashbonus);
2888 if (tutoriallevel != 1) {
2889 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2890 victim->DoBloodBig(2 / victim->armorhigh, 190);
2892 victim->DoBloodBig(2 / victim->armorhigh, 185);
2893 victim->deathbleeding = 1;
2894 emit_sound_at(swordslicesound, victim->coords);
2896 //victim->jointVel(abdomen)+=relative*damagemult*200;
2897 if (tutoriallevel != 1) {
2898 victim->frameTarget = 0;
2899 victim->animTarget = staggerbackhardanim;
2900 victim->targetyaw = targetyaw + 180;
2904 if (tutoriallevel != 1) {
2905 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2906 weapons[weaponids[weaponactive]].bloody = 1;
2907 weapons[weaponids[weaponactive]].blooddrip += 3;
2909 float bloodlossamount;
2910 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2911 victim->bloodloss += bloodlossamount / victim->armorhigh;
2912 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2913 victim->DoDamage(damagemult * 0);
2915 XYZ footvel, footpoint;
2917 if (skeleton.free) {
2918 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2920 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2923 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2924 footvel = DoRotation(facing, 0, 90, 0) * .8;
2926 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2927 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2928 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2929 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2932 if (victim->weaponactive != -1) {
2933 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2934 if (weapons[victim->weaponids[0]].getType() == staff)
2935 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2936 if (weapons[weaponids[0]].getType() == staff)
2937 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2939 emit_sound_at(swordstaffsound, victim->coords);
2941 emit_sound_at(metalhitsound, victim->coords);
2947 victim->Puff(righthand);
2949 victim->frameTarget = 0;
2950 victim->animTarget = staggerbackhighanim;
2951 victim->targetyaw = targetyaw + 180;
2953 aim = DoRotation(facing, 0, 90, 0) * 21;
2955 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2956 victim->num_weapons--;
2957 if (victim->num_weapons) {
2958 victim->weaponids[0] = victim->weaponids[num_weapons];
2959 if (victim->weaponstuck == victim->num_weapons)
2960 victim->weaponstuck = 0;
2962 victim->weaponactive = -1;
2963 for (unsigned i = 0; i < Person::players.size(); i++) {
2964 Person::players[i]->wentforweapon = 0;
2971 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2972 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2973 if (tutoriallevel != 1) {
2974 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2978 if (Random() % 2 || creature == wolftype) {
2981 emit_sound_at(staffheadsound, victim->coords);
2985 relative = victim->coords - coords;
2987 Normalise(&relative);
2988 relative = DoRotation(relative, 0, 90, 0);
2990 Normalise(&relative);
2991 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2992 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2994 victim->jointVel(head) += relative * damagemult * 230;
2995 victim->jointVel(neck) += relative * damagemult * 230;
2998 if (tutoriallevel != 1) {
2999 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3001 award_bonus(id, solidhit, 30);
3006 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3007 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3008 if (tutoriallevel != 1) {
3009 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3013 if (Random() % 2 || creature == wolftype) {
3016 emit_sound_at(staffheadsound, victim->coords);
3020 relative = victim->coords - coords;
3022 Normalise(&relative);
3023 relative = DoRotation(relative, 0, -90, 0);
3024 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3025 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3027 victim->jointVel(head) += relative * damagemult * 220;
3028 victim->jointVel(neck) += relative * damagemult * 220;
3031 if (tutoriallevel != 1) {
3032 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3034 award_bonus(id, solidhit, 60);
3039 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3040 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3042 if (tutoriallevel != 1) {
3044 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3047 if (Random() % 2 || creature == wolftype) {
3050 emit_sound_at(staffbodysound, victim->coords);
3052 victim->skeleton.longdead = 0;
3053 victim->skeleton.free = 1;
3054 victim->skeleton.broken = 0;
3056 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3057 victim->skeleton.joints[i].velchange = 0;
3058 victim->skeleton.joints[i].locked = 0;
3059 //victim->skeleton.joints[i].velocity=0;
3065 /*relative=victim->coords-coords;
3067 Normalise(&relative);
3068 relative=DoRotation(relative,0,90,0);*/
3070 Normalise(&relative);
3071 if (!victim->dead) {
3072 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3073 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3076 victim->jointVel(abdomen) += relative * damagemult * 40;
3079 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3080 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3083 //victim->jointVel(abdomen)+=relative*damagemult*20;
3085 victim->Puff(abdomen);
3086 if (tutoriallevel != 1) {
3087 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3089 if (!victim->dead) {
3090 award_bonus(id, solidhit, 40);
3096 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3097 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3102 relative = victim->coords - coords;
3104 Normalise(&relative);
3108 if (animation[victim->animTarget].height == lowheight) {
3114 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3115 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3117 victim->jointVel(head) += relative * damagemult * 200;
3118 if (tutoriallevel != 1) {
3119 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3122 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3123 if (victim->howactive == typesleeping)
3124 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3125 if (creature == wolftype) {
3126 emit_sound_at(clawslicesound, victim->coords, 128.);
3128 victim->DoBloodBig(2 / victim->armorhead, 175);
3131 if (victim->damage >= victim->damagetolerance)
3133 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3134 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3136 victim->jointVel(abdomen) += relative * damagemult * 200;
3137 victim->frameTarget = 0;
3138 victim->animTarget = staggerbackhighanim;
3139 victim->targetyaw = targetyaw + 180;
3141 if (tutoriallevel != 1) {
3142 emit_sound_at(landsound2, victim->coords, 128.);
3144 victim->Puff(abdomen);
3145 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3146 if (creature == wolftype) {
3147 emit_sound_at(clawslicesound, victim->coords, 128.);
3149 victim->DoBloodBig(2 / victim->armorhigh, 170);
3156 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3157 if ((victim->animTarget != jumpupanim) &&
3158 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3159 (victim != this->shared_from_this())) {
3163 if (tutoriallevel != 1) {
3164 emit_sound_at(landsound2, victim->coords, 128.);
3167 relative = victim->coords - coords;
3169 Normalise(&relative);
3171 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3174 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3175 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3177 relative = DoRotation(relative, 0, -90, 0);
3179 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3180 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)
3181 victim->skeleton.joints[i].velocity = relative * 80;
3183 victim->Puff(rightankle);
3184 victim->Puff(leftankle);
3185 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3187 if (victim->damage >= victim->damagetolerance)
3189 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3190 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3192 relative = DoRotation(relative, 0, -90, 0);
3193 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3194 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)
3195 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3197 victim->jointVel(abdomen) += relative * damagemult * 200;
3198 victim->frameTarget = 0;
3199 victim->animTarget = staggerbackhighanim;
3200 victim->targetyaw = targetyaw + 180;
3202 if (tutoriallevel != 1) {
3203 emit_sound_at(landsound2, victim->coords, 128.);
3205 victim->Puff(abdomen);
3206 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3214 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3215 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3223 if (tutoriallevel != 1) {
3224 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3226 if (creature == wolftype) {
3227 emit_sound_at(clawslicesound, victim->coords, 128);
3229 victim->DoBloodBig(2 / victim->armorhigh, 170);
3233 relative = victim->coords - oldcoords;
3235 Normalise(&relative);
3236 //relative=DoRotation(relative,0,-90,0);
3237 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3238 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3240 victim->jointVel(abdomen) += relative * damagemult * 200;
3242 victim->Puff(abdomen);
3243 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3245 award_bonus(id, Reversal);
3248 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3249 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3250 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3251 takeWeapon(victim->weaponids[victim->weaponactive]);
3252 victim->num_weapons--;
3253 if (victim->num_weapons > 0) {
3254 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3256 victim->weaponactive = -1;
3261 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3269 emit_sound_at(whooshhitsound, victim->coords, 128.);
3272 relative = victim->coords - oldcoords;
3274 Normalise(&relative);
3275 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3276 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3278 victim->jointVel(abdomen) += relative * damagemult * 200;
3280 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3283 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3292 award_bonus(id, staffreversebonus);
3294 if (tutoriallevel != 1) {
3295 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3298 award_bonus(id, staffreversebonus); // Huh, again?
3301 relative = victim->coords - oldcoords;
3303 Normalise(&relative);
3304 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3305 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3307 victim->jointVel(abdomen) += relative * damagemult * 200;
3309 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3312 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3318 Normalise(&relative);
3320 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3321 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3323 victim->jointVel(lefthand) *= .1;
3324 victim->jointVel(leftwrist) *= .2;
3325 victim->jointVel(leftelbow) *= .5;
3326 victim->jointVel(leftshoulder) *= .7;
3327 victim->jointVel(righthand) *= .1;
3328 victim->jointVel(rightwrist) *= .2;
3329 victim->jointVel(rightelbow) *= .5;
3330 victim->jointVel(rightshoulder) *= .7;
3332 victim->Puff(abdomen);
3333 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3335 award_bonus(id, Reversal);
3339 if (weaponactive != -1 || creature == wolftype)
3341 if (creature == rabbittype && weaponactive != -1)
3342 if (weapons[weaponids[0]].getType() == staff)
3345 if (weaponactive != -1) {
3346 victim->DoBloodBig(2 / victim->armorhigh, 225);
3347 emit_sound_at(knifeslicesound, victim->coords);
3348 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3349 weapons[weaponids[weaponactive]].bloody = 1;
3350 weapons[weaponids[weaponactive]].blooddrip += 3;
3352 if (weaponactive == -1 && creature == wolftype) {
3354 emit_sound_at(clawslicesound, victim->coords, 128.);
3356 victim->DoBloodBig(2 / victim->armorhigh, 175);
3363 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3369 Normalise(&relative);
3371 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3372 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3374 victim->jointVel(lefthand) *= .1 - 1;
3375 victim->jointVel(leftwrist) *= .2 - 1;
3376 victim->jointVel(leftelbow) *= .5 - 1;
3377 victim->jointVel(leftshoulder) *= .7 - 1;
3378 victim->jointVel(righthand) *= .1 - 1;
3379 victim->jointVel(rightwrist) *= .2 - 1;
3380 victim->jointVel(rightelbow) *= .5 - 1;
3381 victim->jointVel(rightshoulder) *= .7 - 1;
3383 award_bonus(id, swordreversebonus);
3386 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3394 if (tutoriallevel != 1) {
3395 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3399 relative = victim->coords - oldcoords;
3401 Normalise(&relative);
3402 relative = DoRotation(relative, 0, -90, 0);
3403 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3404 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3406 victim->jointVel(abdomen) += relative * damagemult * 200;
3407 victim->Puff(abdomen);
3408 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3410 award_bonus(id, Reversal);
3413 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3416 victim->skeleton.spinny = 0;
3418 relative = facing * -1;
3420 Normalise(&relative);
3421 if (victim->id == 0)
3423 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3424 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3426 victim->damage = victim->damagetolerance;
3427 victim->permanentdamage = victim->damagetolerance - 1;
3430 if (weaponactive != -1 || creature == wolftype)
3432 if (creature == rabbittype && weaponactive != -1)
3433 if (weapons[weaponids[0]].getType() == staff)
3436 if (weaponactive != -1) {
3437 victim->DoBloodBig(200, 225);
3438 emit_sound_at(knifeslicesound, victim->coords);
3440 weapons[weaponids[weaponactive]].bloody = 2;
3441 weapons[weaponids[weaponactive]].blooddrip += 5;
3444 if (creature == wolftype && weaponactive == -1) {
3445 emit_sound_at(clawslicesound, victim->coords, 128.);
3447 victim->DoBloodBig(2, 175);
3450 award_bonus(id, spinecrusher);
3453 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3454 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3456 if (animTarget == knifefollowanim)
3457 victim->DoBloodBig(200, 210);
3458 if (animTarget == knifesneakattackanim) {
3459 XYZ footvel, footpoint;
3461 footpoint = weapons[weaponids[0]].tippoint;
3463 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3464 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3465 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3466 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3467 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3468 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3469 victim->DoBloodBig(200, 195);
3470 award_bonus(id, tracheotomy);
3472 if (animTarget == knifefollowanim) {
3473 award_bonus(id, Stabbonus);
3474 XYZ footvel, footpoint;
3476 footpoint = weapons[weaponids[0]].tippoint;
3478 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3479 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3480 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3481 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3482 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3483 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3486 victim->bloodloss += 10000;
3487 victim->velocity = 0;
3488 emit_sound_at(fleshstabsound, victim->coords);
3490 weapons[weaponids[weaponactive]].bloody = 2;
3491 weapons[weaponids[weaponactive]].blooddrip += 5;
3495 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3497 victim->velocity = 0;
3498 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3499 victim->skeleton.joints[i].velocity = 0;
3501 if (animTarget == knifefollowanim) {
3503 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3504 victim->skeleton.joints[i].velocity = 0;
3507 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3508 emit_sound_at(fleshstabremovesound, victim->coords);
3510 weapons[weaponids[weaponactive]].bloody = 2;
3511 weapons[weaponids[weaponactive]].blooddrip += 5;
3513 XYZ footvel, footpoint;
3515 footpoint = weapons[weaponids[0]].tippoint;
3517 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3518 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3519 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3520 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3521 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3522 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3526 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3527 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3528 award_bonus(id, backstab);
3532 XYZ footvel, footpoint;
3534 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3536 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3537 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3538 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3539 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3541 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3542 victim->DoBloodBig(200, 180);
3543 victim->DoBloodBig(200, 215);
3544 victim->bloodloss += 10000;
3545 victim->velocity = 0;
3546 emit_sound_at(fleshstabsound, victim->coords);
3548 weapons[weaponids[weaponactive]].bloody = 2;
3549 weapons[weaponids[weaponactive]].blooddrip += 5;
3553 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3555 victim->velocity = 0;
3556 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3557 victim->skeleton.joints[i].velocity = 0;
3559 if (weaponactive != -1) {
3560 emit_sound_at(fleshstabremovesound, victim->coords);
3562 weapons[weaponids[weaponactive]].bloody = 2;
3563 weapons[weaponids[weaponactive]].blooddrip += 5;
3565 XYZ footvel, footpoint;
3567 footpoint = weapons[weaponids[0]].tippoint;
3569 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3570 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
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, footvel * 5, 1, 1, 1, .3, 1);
3574 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3578 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3586 if (weaponactive == -1) {
3587 if (tutoriallevel != 1) {
3588 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3593 if (weaponactive != -1 || creature == wolftype)
3595 if (creature == rabbittype && weaponactive != -1)
3596 if (weapons[weaponids[0]].getType() == staff)
3599 if (weaponactive != -1) {
3600 victim->DoBloodBig(2 / victim->armorhead, 225);
3601 emit_sound_at(knifeslicesound, victim->coords);
3602 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3603 weapons[weaponids[weaponactive]].bloody = 1;
3604 weapons[weaponids[weaponactive]].blooddrip += 3;
3606 if (weaponactive == -1 && creature == wolftype) {
3607 emit_sound_at(clawslicesound, victim->coords, 128.);
3609 victim->DoBloodBig(2 / victim->armorhead, 175);
3613 award_bonus(id, Reversal);
3618 relative = facing * -1;
3620 Normalise(&relative);
3621 relative = DoRotation(relative, 0, 90, 0);
3623 Normalise(&relative);
3624 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3625 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3627 victim->jointVel(head) += relative * damagemult * 200;
3628 if (victim->damage < victim->damagetolerance - 100)
3629 victim->velocity = relative * 200;
3630 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3631 victim->velocity = 0;
3634 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3638 relative = facing * -1;
3640 Normalise(&relative);
3641 relative = DoRotation(relative, 0, 90, 0);
3643 Normalise(&relative);
3644 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3645 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3647 victim->jointVel(head) += relative * damagemult * 200;
3650 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3651 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3652 award_bonus(id, reverseko);
3658 if (frameTarget > animation[animCurrent].numframes - 1) {
3661 animTarget = getIdle();
3665 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3666 animTarget = rollanim;
3668 emit_sound_at(movewhooshsound, coords, 128.);
3670 if (animCurrent == staggerbackhighanim) {
3671 animTarget = getIdle();
3673 if (animCurrent == staggerbackhardanim) {
3674 animTarget = getIdle();
3676 if (animCurrent == removeknifeanim) {
3677 animTarget = getIdle();
3679 if (animCurrent == crouchremoveknifeanim) {
3680 animTarget = getCrouch();
3682 if (animCurrent == backhandspringanim) {
3683 animTarget = getIdle();
3685 if (animCurrent == dodgebackanim) {
3686 animTarget = getIdle();
3688 if (animCurrent == drawleftanim) {
3689 animTarget = getIdle();
3691 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3692 animTarget = getIdle();
3693 if (animCurrent == crouchdrawrightanim) {
3694 animTarget = getCrouch();
3696 if (weaponactive == -1)
3698 else if (weaponactive == 0) {
3700 if (num_weapons == 2) {
3702 buffer = weaponids[0];
3703 weaponids[0] = weaponids[1];
3704 weaponids[1] = buffer;
3708 if (weaponactive == -1) {
3709 emit_sound_at(knifesheathesound, coords, 128.);
3711 if (weaponactive != -1) {
3712 emit_sound_at(knifedrawsound, coords, 128.);
3715 if (animCurrent == rollanim) {
3716 animTarget = getCrouch();
3721 if (animTarget == walljumprightkickanim) {
3724 if (animTarget == walljumpleftkickanim) {
3727 animTarget = jumpdownanim;
3729 if (animCurrent == climbanim) {
3730 animTarget = getCrouch();
3732 coords += facing * .1;
3733 if (!isnormal(coords.x))
3744 if (animTarget == rabbitkickreversalanim) {
3745 animTarget = getCrouch();
3748 if (animTarget == jumpreversalanim) {
3749 animTarget = getCrouch();
3752 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3753 if (attackkeydown && animTarget != walljumpfrontanim) {
3755 float closestdist = -1;
3757 if (Person::players.size() > 1)
3758 for (unsigned i = 0; i < Person::players.size(); i++) {
3759 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3760 distance = distsq(&Person::players[i]->coords, &coords);
3761 if (closestdist == -1 || distance < closestdist) {
3762 closestdist = distance;
3767 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3768 victim = Person::players[closest];
3769 animTarget = walljumprightkickanim;
3771 XYZ rotatetarget = victim->coords - coords;
3772 Normalise(&rotatetarget);
3773 yaw = -asin(0 - rotatetarget.x);
3775 if (rotatetarget.z < 0)
3777 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3778 velocity = (victim->coords - coords) * 4;
3783 if (animTarget == walljumpbackanim) {
3784 animTarget = backflipanim;
3786 velocity = facing * -8;
3789 resume_stream(whooshsound);
3791 if (animTarget == walljumprightanim) {
3792 animTarget = rightflipanim;
3796 velocity = DoRotation(facing, 0, 30, 0) * -8;
3799 if (animTarget == walljumpfrontanim) {
3800 animTarget = frontflipanim;
3804 velocity = facing * 8;
3808 resume_stream(whooshsound);
3810 if (animTarget == walljumpleftanim) {
3811 if (attackkeydown) {
3813 float closestdist = -1;
3815 if (Person::players.size() > 1)
3816 for (unsigned i = 0; i < Person::players.size(); i++) {
3817 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3818 distance = distsq(&Person::players[i]->coords, &coords);
3819 if (closestdist == -1 || distance < closestdist) {
3820 closestdist = distance;
3825 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3826 victim = Person::players[closest];
3827 animTarget = walljumpleftkickanim;
3829 XYZ rotatetarget = victim->coords - coords;
3830 Normalise(&rotatetarget);
3831 yaw = -asin(0 - rotatetarget.x);
3833 if (rotatetarget.z < 0)
3835 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3836 velocity = (victim->coords - coords) * 4;
3841 if (animTarget != walljumpleftkickanim) {
3842 animTarget = leftflipanim;
3846 velocity = DoRotation(facing, 0, -30, 0) * -8;
3850 resume_stream(whooshsound);
3852 if (animTarget == sneakattackanim) {
3853 animCurrent = getCrouch();
3854 animTarget = getCrouch();
3861 transspeed = 1000000;
3862 targetheadyaw += 180;
3863 coords -= facing * .7;
3865 coords.y = terrain.getHeight(coords.x, coords.z);
3869 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3870 animTarget = getIdle();
3873 coords.y = terrain.getHeight(coords.x, coords.z);
3877 if (animCurrent == knifefollowanim) {
3878 animTarget = getIdle();
3881 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3882 float ycoords = oldcoords.y;
3883 animTarget = getStop();
3888 transspeed = 1000000;
3889 targetheadyaw += 180;
3890 if (!isnormal(coords.x))
3892 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3893 oldcoords = coords + facing * .5;
3894 else if (animCurrent == sweepreversalanim)
3895 oldcoords = coords + facing * 1.1;
3896 else if (animCurrent == upunchreversalanim) {
3897 oldcoords = coords + facing * 1.5;
3900 targetheadyaw += 180;
3903 } else if (animCurrent == knifeslashreversalanim) {
3904 oldcoords = coords + facing * .5;
3907 targetheadyaw += 90;
3910 } else if (animCurrent == staffspinhitreversalanim) {
3913 targetheadyaw += 180;
3918 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3920 oldcoords.y = ycoords;
3921 currentoffset = coords - oldcoords;
3927 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3932 if (animation[animTarget].attack == reversed) {
3934 if (animTarget == sweepreversedanim)
3936 animTarget = backhandspringanim;
3938 emit_sound_at(landsound, coords, 128);
3940 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3941 animTarget = rollanim;
3944 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3945 coords.y = oldcoords.y;
3947 if (animCurrent == knifeslashreversedanim) {
3948 animTarget = rollanim;
3953 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3954 coords.y = oldcoords.y;
3958 animTarget = jumpdownanim;
3961 animTarget = getIdle();
3963 animTarget = getIdle();
3964 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3965 animTarget = getIdle();
3967 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3968 coords.y = oldcoords.y;
3969 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3970 targetoffset.y = coords.y;
3972 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3973 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3974 currentoffset.y -= (coords.y - targetoffset.y);
3975 coords.y = targetoffset.y;
3977 normalsupdatedelay = 0;
3979 if (animCurrent == upunchanim) {
3980 animTarget = getStop();
3981 normalsupdatedelay = 0;
3984 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3988 if (num_weapons > 0)
3989 if (weapons[0].getType() == staff)
3995 rabbitkickragdoll = 1;
3997 if (animCurrent == rabbitkickreversedanim) {
4003 skeleton.spinny = 0;
4004 SolidHitBonus(!id); // FIXME: tricky id
4008 animTarget = rollanim;
4011 pause_sound(whooshsound);
4015 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4019 skeleton.spinny = 0;
4021 if (animCurrent == jumpreversedanim) {
4027 skeleton.spinny = 0;
4028 SolidHitBonus(!id); // FIXME: tricky id
4032 animTarget = rollanim;
4033 coords += facing * 2;
4035 pause_sound(whooshsound);
4040 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) {
4041 animTarget = getupfromfrontanim;
4043 } else if (animation[animCurrent].attack == normalattack) {
4044 animTarget = getIdle();
4047 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4048 animTarget = blockhighleftstrikeanim;
4050 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4051 animTarget = getIdle();
4054 if (animCurrent == spinkickanim && victim->skeleton.free) {
4055 if (creature == rabbittype)
4056 animTarget = fightidleanim;
4061 if (isIdle() && !wasIdle())
4062 normalsupdatedelay = 0;
4064 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4065 animTarget = jumpdownanim;
4068 if (!skeleton.free) {
4070 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4071 if (!isRun() || !wasRun()) {
4072 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4073 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4074 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4075 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4077 if (isRun() && wasRun()) {
4079 tempspeed = velspeed;
4080 if (tempspeed < 10 * speedmult)
4081 tempspeed = 10 * speedmult;
4082 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4084 } else if (transspeed)
4085 target += multiplier * transspeed * speed * 2;
4087 if (!isRun() || !wasRun()) {
4088 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4089 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4090 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4091 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4095 if (animCurrent != animTarget)
4096 target = (target + oldtarget) / 2;
4099 frameCurrent = frameTarget;
4103 rot = targetrot * target;
4104 yaw += rot - oldrot;
4110 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4112 for (int i = 0; i < skeleton.num_joints; i++) {
4113 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4116 skeleton.FindForwards();
4118 for (int i = 0; i < skeleton.num_muscles; i++) {
4119 if (skeleton.muscles[i].visible) {
4120 skeleton.FindRotationMuscle(i, animTarget);
4123 for (int i = 0; i < skeleton.num_muscles; i++) {
4124 if (skeleton.muscles[i].visible) {
4125 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4126 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4127 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4128 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4129 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4130 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4135 for (int i = 0; i < skeleton.num_joints; i++) {
4136 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4139 skeleton.FindForwards();
4141 for (int i = 0; i < skeleton.num_muscles; i++) {
4142 if (skeleton.muscles[i].visible) {
4143 skeleton.FindRotationMuscle(i, animTarget);
4146 for (int i = 0; i < skeleton.num_muscles; i++) {
4147 if (skeleton.muscles[i].visible) {
4148 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4149 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4150 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4151 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4152 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4153 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4154 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4155 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4156 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4157 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4158 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4159 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4163 if (frameCurrent >= animation[animCurrent].numframes)
4164 frameCurrent = animation[animCurrent].numframes - 1;
4166 oldanimCurrent = animCurrent;
4167 oldanimTarget = animTarget;
4168 oldframeTarget = frameTarget;
4169 oldframeCurrent = frameCurrent;
4171 for (int i = 0; i < skeleton.num_joints; i++) {
4172 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4173 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4175 offset = currentoffset * (1 - target) + targetoffset * target;
4176 for (int i = 0; i < skeleton.num_muscles; i++) {
4177 if (skeleton.muscles[i].visible) {
4178 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4179 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4180 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4185 if (isLanding() && landhard) {
4188 animTarget = getLandhard();
4201 void Person::DoStuff()
4203 static XYZ terrainnormal;
4204 static XYZ flatfacing;
4205 static XYZ flatvelocity;
4206 static float flatvelspeed;
4210 static int bloodsize;
4211 static int startx, starty, endx, endy;
4212 static GLubyte color;
4213 static XYZ bloodvel;
4215 onfiredelay -= multiplier;
4216 if (onfiredelay < 0 && onfire) {
4217 if (Random() % 2 == 0) {
4223 crouchkeydowntime += multiplier;
4225 crouchkeydowntime = 0;
4226 jumpkeydowntime += multiplier;
4227 if (!jumpkeydown && skeleton.free)
4228 jumpkeydowntime = 0;
4230 if (hostile || damage > 0 || bloodloss > 0)
4233 if (isIdle() || isRun())
4236 if (num_weapons == 1 && weaponactive != -1)
4240 blooddimamount -= multiplier * .3;
4241 speechdelay -= multiplier;
4242 texupdatedelay -= multiplier;
4243 interestdelay -= multiplier;
4244 flamedelay -= multiplier;
4245 parriedrecently -= multiplier;
4247 victim = this->shared_from_this();
4252 speed = 1.1 * speedmult;
4254 speed = 1.0 * speedmult;
4256 rabbitkickragdoll = 0;
4260 if (id != 0 && (creature == rabbittype || difficulty != 2))
4262 if (id != 0 && creature == wolftype && difficulty == 2) {
4264 if (aitype != passivetype) {
4266 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) {
4272 if (animTarget == wolfrunninganim && !superruntoggle) {
4273 animTarget = getRun();
4277 if (weaponactive == -1 && num_weapons > 0) {
4278 if (weapons[weaponids[0]].getType() == staff) {
4284 burnt += multiplier;
4288 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4290 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4296 vel[0] = velocity.x;
4297 vel[1] = velocity.y;
4298 vel[2] = velocity.z;
4301 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4302 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4306 while (flamedelay < 0 && onfire) {
4308 howmany = abs(Random() % (skeleton.num_joints));
4309 if (skeleton.free) {
4310 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4311 flatfacing = skeleton.joints[howmany].position * scale + coords;
4313 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4314 flatvelocity = (coords - oldcoords) / multiplier / 2;
4316 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4319 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4321 howmany = abs(Random() % (skeleton.num_joints));
4322 if (skeleton.free) {
4323 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4324 flatfacing = skeleton.joints[howmany].position * scale + coords;
4326 flatvelocity = (coords - oldcoords) / multiplier / 2;
4327 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4329 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4333 bleeding -= multiplier * .3;
4334 if (bloodtoggle == 2) {
4335 skeleton.drawmodel.textureptr.bind();
4336 if ((bleeding <= 0) && (detail != 2))
4341 if (neckspurtamount > 0) {
4342 neckspurtamount -= multiplier;
4343 neckspurtdelay -= multiplier * 3;
4344 neckspurtparticledelay -= multiplier * 3;
4345 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4348 if (skeleton.free) {
4349 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4350 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4351 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4353 bloodvel.z = 5 * neckspurtamount;
4354 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4355 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4356 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4358 neckspurtparticledelay = .05;
4360 if (neckspurtdelay < 0) {
4365 if (deathbleeding > 0 && dead != 2) {
4366 if (deathbleeding < 5)
4367 bleeddelay -= deathbleeding * multiplier / 4;
4369 bleeddelay -= 5 * multiplier / 4;
4370 if (bleeddelay < 0 && bloodtoggle) {
4375 if (skeleton.free) {
4376 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4377 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4379 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4380 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4384 bloodloss += deathbleeding * multiplier * 80;
4385 deathbleeding -= multiplier * 1.6;
4386 if (deathbleeding < 0)
4388 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4389 if (weaponactive != -1) {
4390 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4391 weapons[weaponids[0]].velocity.x += .01;
4394 weaponids[0] = weaponids[num_weapons];
4395 if (weaponstuck == num_weapons)
4399 for (unsigned i = 0; i < Person::players.size(); i++) {
4400 Person::players[i]->wentforweapon = 0;
4412 if (!dead && creature == wolftype) {
4413 award_bonus(0, Wolfbonus);
4416 if (animTarget == knifefollowedanim && !skeleton.free) {
4417 for (int i = 0; i < skeleton.num_joints; i++) {
4418 skeleton.joints[i].velocity = 0;
4419 skeleton.joints[i].velocity.y = -2;
4422 if (id != 0 && unconscioustime > .1) {
4430 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4431 texupdatedelay = .12;
4433 bloodsize = 5 - realtexdetail;
4437 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4438 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4439 endx = startx + bloodsize;
4440 endy = starty + bloodsize;
4450 if (endx > skeleton.skinsize - 1) {
4451 endx = skeleton.skinsize - 1;
4454 if (endy > skeleton.skinsize - 1) {
4455 endy = skeleton.skinsize - 1;
4463 for (i = startx; i < endx; i++) {
4464 for (j = starty; j < endy; j++) {
4465 if (Random() % 2 == 0) {
4466 color = Random() % 85 + 170;
4467 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4468 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4469 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4470 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4475 skeleton.drawmodel.textureptr.bind();
4479 if (skeleton.free) {
4480 bleedx += 4 * direction / realtexdetail;
4482 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4484 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4486 bleedy -= 4 / realtexdetail;
4488 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4490 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4494 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4495 righthandmorphness = targetrighthandmorphness;
4496 righthandmorphstart = righthandmorphend;
4497 } else if (righthandmorphness > targetrighthandmorphness) {
4498 righthandmorphness -= multiplier * 4;
4499 } else if (righthandmorphness < targetrighthandmorphness) {
4500 righthandmorphness += multiplier * 4;
4503 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4504 lefthandmorphness = targetlefthandmorphness;
4505 lefthandmorphstart = lefthandmorphend;
4506 } else if (lefthandmorphness > targetlefthandmorphness) {
4507 lefthandmorphness -= multiplier * 4;
4508 } else if (lefthandmorphness < targetlefthandmorphness) {
4509 lefthandmorphness += multiplier * 4;
4512 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4513 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4514 tailmorphness = targettailmorphness;
4515 tailmorphstart = tailmorphend;
4516 } else if (tailmorphness > targettailmorphness) {
4517 tailmorphness -= multiplier * 10;
4518 } else if (tailmorphness < targettailmorphness) {
4519 tailmorphness += multiplier * 10;
4523 if (creature == wolftype) {
4524 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4525 tailmorphness = targettailmorphness;
4526 tailmorphstart = tailmorphend;
4527 } else if (tailmorphness > targettailmorphness) {
4528 tailmorphness -= multiplier * 2;
4529 } else if (tailmorphness < targettailmorphness) {
4530 tailmorphness += multiplier * 2;
4534 if (headmorphend == 3 || headmorphstart == 3) {
4535 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4536 headmorphness = targetheadmorphness;
4537 headmorphstart = headmorphend;
4538 } else if (headmorphness > targetheadmorphness) {
4539 headmorphness -= multiplier * 7;
4540 } else if (headmorphness < targetheadmorphness) {
4541 headmorphness += multiplier * 7;
4543 } else if (headmorphend == 5 || headmorphstart == 5) {
4544 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4545 headmorphness = targetheadmorphness;
4546 headmorphstart = headmorphend;
4547 } else if (headmorphness > targetheadmorphness) {
4548 headmorphness -= multiplier * 10;
4549 } else if (headmorphness < targetheadmorphness) {
4550 headmorphness += multiplier * 10;
4553 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4554 headmorphness = targetheadmorphness;
4555 headmorphstart = headmorphend;
4556 } else if (headmorphness > targetheadmorphness) {
4557 headmorphness -= multiplier * 4;
4558 } else if (headmorphness < targetheadmorphness) {
4559 headmorphness += multiplier * 4;
4563 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4564 chestmorphness = targetchestmorphness;
4565 chestmorphstart = chestmorphend;
4566 } else if (chestmorphness > targetchestmorphness) {
4567 chestmorphness -= multiplier;
4568 } else if (chestmorphness < targetchestmorphness) {
4569 chestmorphness += multiplier;
4572 if (dead != 2 && howactive <= typesleeping) {
4573 if (chestmorphstart == 0 && chestmorphend == 0) {
4575 targetchestmorphness = 1;
4578 if (chestmorphstart != 0 && chestmorphend != 0) {
4580 targetchestmorphness = 1;
4582 if (environment == snowyenvironment) {
4585 if (skeleton.free) {
4586 footvel = skeleton.specialforward[0] * -1;
4587 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4589 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4590 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4592 if (animTarget == sleepanim)
4593 footvel = DoRotation(footvel, 0, 90, 0);
4594 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4598 if (!dead && howactive < typesleeping) {
4599 blinkdelay -= multiplier * 2;
4600 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4602 targetheadmorphness = 1;
4604 blinkdelay = (float)(abs(Random() % 40)) / 5;
4606 if (headmorphstart == 3 && headmorphend == 3) {
4608 targetheadmorphness = 1;
4613 twitchdelay -= multiplier * 1.5;
4614 if (animTarget != hurtidleanim) {
4615 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4617 targetheadmorphness = 1;
4619 twitchdelay = (float)(abs(Random() % 40)) / 5;
4621 if (headmorphstart == 5 && headmorphend == 5) {
4623 targetheadmorphness = 1;
4627 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4628 twitchdelay3 -= multiplier * 1;
4629 if (Random() % 2 == 0) {
4630 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4631 righthandmorphness = 0;
4632 targetrighthandmorphness = 1;
4633 righthandmorphend = 1;
4634 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4636 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4637 righthandmorphness = 0;
4638 targetrighthandmorphness = 1;
4639 righthandmorphend = 0;
4642 if (Random() % 2 == 0) {
4643 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4644 lefthandmorphness = 0;
4645 targetlefthandmorphness = 1;
4646 lefthandmorphend = 1;
4647 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4649 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4650 lefthandmorphness = 0;
4651 targetlefthandmorphness = 1;
4652 lefthandmorphend = 0;
4658 if (creature == rabbittype) {
4659 if (howactive < typesleeping)
4660 twitchdelay2 -= multiplier * 1.5;
4662 twitchdelay2 -= multiplier * 0.5;
4663 if (howactive <= typesleeping) {
4664 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4666 targettailmorphness = 1;
4668 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4670 if (tailmorphstart == 1 && tailmorphend == 1) {
4672 targettailmorphness = 1;
4675 if (tailmorphstart == 2 && tailmorphend == 2) {
4677 targettailmorphness = 1;
4684 if (creature == wolftype) {
4685 twitchdelay2 -= multiplier * 1.5;
4686 if (tailmorphend != 0)
4687 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4689 targettailmorphness = 1;
4693 if (tailmorphend != 5)
4694 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4696 targettailmorphness = 1;
4700 if (twitchdelay2 <= 0) {
4701 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4703 targettailmorphness = 1;
4706 if (tailmorphstart == 1 && tailmorphend == 1) {
4708 targettailmorphness = 1;
4711 if (tailmorphstart == 2 && tailmorphend == 2) {
4713 targettailmorphness = 1;
4716 if (tailmorphstart == 3 && tailmorphend == 3) {
4718 targettailmorphness = 1;
4721 if (tailmorphstart == 4 && tailmorphend == 4) {
4723 targettailmorphness = 1;
4730 unconscioustime = 0;
4732 if (dead == 1 || howactive == typesleeping) {
4733 unconscioustime += multiplier;
4734 //If unconscious, close eyes and mouth
4735 if (righthandmorphend != 0)
4736 righthandmorphness = 0;
4737 righthandmorphend = 0;
4738 targetrighthandmorphness = 1;
4740 if (lefthandmorphend != 0)
4741 lefthandmorphness = 0;
4742 lefthandmorphend = 0;
4743 targetlefthandmorphness = 1;
4745 if (headmorphend != 3 && headmorphend != 5)
4748 targetheadmorphness = 1;
4752 if (howactive > typesleeping) {
4755 if (bloodtoggle && !bled) {
4756 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4758 if (bloodtoggle && !bled)
4759 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4760 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4761 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4765 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4770 if (dead == 2 || howactive > typesleeping) {
4771 //If dead, open mouth and hands
4772 if (righthandmorphend != 0)
4773 righthandmorphness = 0;
4774 righthandmorphend = 0;
4775 targetrighthandmorphness = 1;
4777 if (lefthandmorphend != 0)
4778 lefthandmorphness = 0;
4779 lefthandmorphend = 0;
4780 targetlefthandmorphness = 1;
4782 if (headmorphend != 2)
4785 targetheadmorphness = 1;
4788 if (stunned > 0 && !dead && headmorphend != 2) {
4789 if (headmorphend != 4)
4792 targetheadmorphness = 1;
4795 if (damage > damagetolerance && !dead) {
4798 unconscioustime = 0;
4800 if (creature == wolftype) {
4801 award_bonus(0, Wolfbonus);
4806 if (weaponactive != -1) {
4807 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4808 weapons[weaponids[0]].velocity.x += .01;
4811 weaponids[0] = weaponids[num_weapons];
4812 if (weaponstuck == num_weapons)
4816 for (unsigned i = 0; i < Person::players.size(); i++) {
4817 Person::players[i]->wentforweapon = 0;
4823 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4832 damage -= multiplier * 13;
4834 permanentdamage -= multiplier * 4;
4835 if (isIdle() || isCrouch()) {
4837 permanentdamage -= multiplier * 4;
4841 if (permanentdamage < 0)
4842 permanentdamage = 0;
4843 if (superpermanentdamage < 0)
4844 superpermanentdamage = 0;
4845 if (permanentdamage < superpermanentdamage) {
4846 permanentdamage = superpermanentdamage;
4848 if (damage < permanentdamage) {
4849 damage = permanentdamage;
4851 if (dead == 1 && damage < damagetolerance) {
4855 for (int i = 0; i < skeleton.num_joints; i++) {
4856 skeleton.joints[i].velocity = 0;
4859 if (permanentdamage > damagetolerance && dead != 2) {
4862 if (weaponactive != -1) {
4863 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4864 weapons[weaponids[0]].velocity.x += .01;
4867 weaponids[0] = weaponids[num_weapons];
4868 if (weaponstuck == num_weapons)
4872 for (unsigned i = 0; i < Person::players.size(); i++) {
4873 Person::players[i]->wentforweapon = 0;
4879 if (!dead && creature == wolftype) {
4880 award_bonus(0, Wolfbonus);
4883 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4884 award_bonus(id, touchofdeath);
4885 if (id != 0 && unconscioustime > .1) {
4893 emit_sound_at(breaksound, coords);
4896 if (skeleton.free == 1) {
4898 pause_sound(whooshsound);
4901 //If knocked over, open hands and close mouth
4902 if (righthandmorphend != 0)
4903 righthandmorphness = 0;
4904 righthandmorphend = 0;
4905 targetrighthandmorphness = 1;
4907 if (lefthandmorphend != 0)
4908 lefthandmorphness = 0;
4909 lefthandmorphend = 0;
4910 targetlefthandmorphness = 1;
4912 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4913 if (headmorphend != 0)
4916 targetheadmorphness = 1;
4920 skeleton.DoGravity(&scale);
4922 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4923 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4924 award_bonus(id, deepimpact);
4925 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4929 for (j = 0; j < skeleton.num_joints; j++) {
4930 average += skeleton.joints[j].position;
4934 coords += average * scale;
4935 for (j = 0; j < skeleton.num_joints; j++) {
4936 skeleton.joints[j].position -= average;
4938 average /= multiplier;
4941 for (int i = 0; i < skeleton.num_joints; i++) {
4942 velocity += skeleton.joints[i].velocity * scale;
4944 velocity /= skeleton.num_joints;
4946 if (!isnormal(velocity.x) && velocity.x) {
4950 if (findLength(&average) < 10 && dead && skeleton.free) {
4951 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4952 if (skeleton.longdead > 2000) {
4953 if (skeleton.longdead > 6000) {
4955 pause_sound(whooshsound);
4960 if (dead == 2 && bloodloss < damagetolerance) {
4962 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4964 if (bloodtoggle && !bled) {
4965 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4967 if (bloodtoggle && !bled)
4968 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4969 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4970 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4971 float size = .2 * 1.2;
4974 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4978 if (dead == 2 && bloodloss >= damagetolerance) {
4980 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4983 if (bloodtoggle && !bled) {
4984 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4986 if (bloodtoggle && !bled)
4987 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4988 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4989 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4993 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5000 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5001 bool canrecover = 1;
5002 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5003 startpoint = coords;
5006 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5008 if (velocity.y < -30)
5010 for (i = 0; i < objects.numobjects; i++) {
5011 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5012 colviewer = startpoint;
5013 coltarget = endpoint;
5014 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5023 terrainnormal = jointPos(groin) - jointPos(abdomen);
5024 if (joint(groin).locked && joint(abdomen).locked) {
5025 terrainnormal = jointPos(groin) - jointPos(abdomen);
5026 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5028 if (joint(abdomen).locked && joint(neck).locked) {
5029 terrainnormal = jointPos(abdomen) - jointPos(neck);
5030 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5032 if (joint(groin).locked && joint(neck).locked) {
5033 terrainnormal = jointPos(groin) - jointPos(neck);
5034 middle = (jointPos(groin) + jointPos(neck)) / 2;
5036 Normalise(&terrainnormal);
5038 targetyaw = -asin(0 - terrainnormal.x);
5039 targetyaw *= 360 / 6.28;
5040 if (terrainnormal.z < 0)
5041 targetyaw = 180 - targetyaw;
5045 animTarget = flipanim;
5046 crouchtogglekeydown = 1;
5051 animCurrent = tempanim;
5055 for (int i = 0; i < skeleton.num_joints; i++) {
5056 tempanimation.position[i][0] = skeleton.joints[i].position;
5057 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5062 if (findLength(&average) < 10 && !dead && skeleton.free) {
5063 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5064 if (skeleton.longdead > (damage + 500) * 1.5) {
5066 pause_sound(whooshsound);
5072 terrainnormal = jointPos(groin) - jointPos(abdomen);
5073 if (joint(groin).locked && joint(abdomen).locked) {
5074 terrainnormal = jointPos(groin) - jointPos(abdomen);
5075 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5077 if (joint(abdomen).locked && joint(neck).locked) {
5078 terrainnormal = jointPos(abdomen) - jointPos(neck);
5079 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5081 if (joint(groin).locked && joint(neck).locked) {
5082 terrainnormal = jointPos(groin) - jointPos(neck);
5083 middle = (jointPos(groin) + jointPos(neck)) / 2;
5085 Normalise(&terrainnormal);
5087 targetyaw = -asin(0 - terrainnormal.x);
5088 targetyaw *= 360 / 6.28;
5089 if (terrainnormal.z < 0)
5090 targetyaw = 180 - targetyaw;
5093 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5096 if (skeleton.forward.y < 0) {
5097 animTarget = getupfrombackanim;
5101 if (skeleton.forward.y > -.3) {
5102 animTarget = getupfromfrontanim;
5110 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5111 animTarget = rollanim;
5112 targetyaw = lookyaw;
5129 if ( !leftkeydown && !rightkeydown)
5136 if (abs(targettilt2) > 50)
5138 animCurrent = tempanim;
5141 tilt2 = targettilt2;
5143 if (middle.y > 0 && animTarget != rollanim)
5144 targetoffset.y = middle.y + 1;
5146 for (int i = 0; i < skeleton.num_joints; i++) {
5147 tempanimation.position[i][0] = skeleton.joints[i].position;
5148 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5155 if (num_weapons > 0)
5156 if (weapons[0].getType() == staff)
5158 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5159 if (velocity.y > -30) {
5161 tempvelocity = velocity;
5162 Normalise(&tempvelocity);
5163 targetyaw = -asin(0 - tempvelocity.x);
5164 targetyaw *= 360 / 6.28;
5166 targetyaw = 180 - targetyaw;
5170 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5171 animTarget = rollanim;
5174 animTarget = backhandspringanim;
5180 emit_sound_at(movewhooshsound, coords, 128.);
5182 animCurrent = animTarget;
5183 frameCurrent = frameTarget - 1;
5195 if (skeleton.freefall == 0)
5200 if (aitype != passivetype || skeleton.free == 1)
5201 if (findLengthfast(&velocity) > .1)
5202 for (i = 0; i < objects.numobjects; i++) {
5203 if (objects.type[i] == firetype)
5204 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) {
5206 if (!objects.onfire[i]) {
5207 emit_sound_at(firestartsound, objects.position[i]);
5209 objects.onfire[i] = 1;
5212 if (objects.onfire[i]) {
5217 if (objects.type[i] == bushtype)
5218 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) {
5220 if (!objects.onfire[i]) {
5221 emit_sound_at(firestartsound, objects.position[i]);
5223 objects.onfire[i] = 1;
5227 if (objects.onfire[i]) {
5231 if (objects.messedwith[i] <= 0) {
5235 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5238 envsound[numenvsounds] = coords;
5239 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5240 envsoundlife[numenvsounds] = .4;
5245 if (environment == grassyenvironment)
5246 howmany = findLength(&velocity) * 4;
5247 if (environment == snowyenvironment)
5248 howmany = findLength(&velocity) * 2;
5250 if (environment != desertenvironment)
5251 for (j = 0; j < howmany; j++) {
5252 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5253 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5254 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5257 pos.x += float(abs(Random() % 100) - 50) / 200;
5258 pos.y += float(abs(Random() % 100) - 50) / 200;
5259 pos.z += float(abs(Random() % 100) - 50) / 200;
5260 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);
5261 Sprite::setLastSpriteSpecial(1);
5263 howmany = findLength(&velocity) * 4;
5265 if (environment == snowyenvironment)
5266 for (j = 0; j < howmany; j++) {
5267 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5268 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5269 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5272 pos.x += float(abs(Random() % 100) - 50) / 200;
5273 pos.y += float(abs(Random() % 100) - 50) / 200;
5274 pos.z += float(abs(Random() % 100) - 50) / 200;
5275 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5276 Sprite::setLastSpriteSpecial(2);
5279 objects.rotx[i] += velocity.x * multiplier * 6;
5280 objects.roty[i] += velocity.z * multiplier * 6;
5281 objects.messedwith[i] = .5;
5284 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5285 if (objects.pitch[i] == 0)
5288 tempcoord = coords - objects.position[i];
5289 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5290 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5291 tempcoord += objects.position[i];
5293 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]) {
5294 if (objects.messedwith[i] <= 0) {
5298 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5301 envsound[numenvsounds] = coords;
5302 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5303 envsoundlife[numenvsounds] = .4;
5308 if (environment == grassyenvironment)
5309 howmany = findLength(&velocity) * 4;
5310 if (environment == snowyenvironment)
5311 howmany = findLength(&velocity) * 2;
5313 if (environment != desertenvironment)
5314 for (j = 0; j < howmany; j++) {
5315 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5316 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5317 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5319 pos += velocity * .1;
5321 pos.x += float(abs(Random() % 100) - 50) / 150;
5322 pos.y += float(abs(Random() % 100) - 50) / 150;
5323 pos.z += float(abs(Random() % 100) - 50) / 150;
5324 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);
5325 Sprite::setLastSpriteSpecial(1);
5327 howmany = findLength(&velocity) * 4;
5329 if (environment == snowyenvironment)
5330 for (j = 0; j < howmany; j++) {
5331 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5332 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5333 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5335 pos += velocity * .1;
5337 pos.x += float(abs(Random() % 100) - 50) / 150;
5338 pos.y += float(abs(Random() % 100) - 50) / 150;
5339 pos.z += float(abs(Random() % 100) - 50) / 150;
5340 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5341 Sprite::setLastSpriteSpecial(2);
5344 objects.messedwith[i] = .5;
5349 if (!skeleton.free) {
5352 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5355 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5357 if (tutoriallevel == 1 && id != 0)
5359 if (play && aitype != playercontrolled) {
5360 int whichsound = -1;
5361 i = abs(Random() % 4);
5362 if (speechdelay <= 0) {
5363 if (creature == rabbittype) {
5365 whichsound = rabbitchitter;
5367 whichsound = rabbitchitter2;
5369 if (creature == wolftype) {
5371 whichsound = growlsound;
5373 whichsound = growl2sound;
5378 if (whichsound != -1) {
5379 emit_sound_at(whichsound, coords);
5383 if (animTarget == staggerbackhighanim)
5385 if (animTarget == staggerbackhardanim)
5387 staggerdelay -= multiplier;
5388 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5390 if (velocity.y < -30 && animTarget == jumpdownanim)
5392 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5393 animTarget = getIdle();
5397 weaponmissdelay -= multiplier;
5398 highreversaldelay -= multiplier;
5399 lowreversaldelay -= multiplier;
5400 lastcollide -= multiplier;
5401 skiddelay -= multiplier;
5402 if (!isnormal(velocity.x) && velocity.x) {
5405 if (!isnormal(targettilt) && targettilt) {
5408 if (!isnormal(targettilt2) && targettilt2) {
5411 if (!isnormal(targetyaw) && targetyaw) {
5415 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5416 //open hands and close mouth
5417 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5418 righthandmorphness = 0;
5419 righthandmorphend = 0;
5420 targetrighthandmorphness = 1;
5423 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5424 lefthandmorphness = 0;
5425 lefthandmorphend = 0;
5426 targetlefthandmorphness = 1;
5429 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5432 targetheadmorphness = 1;
5436 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) {
5437 //open hands and mouth
5438 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5439 righthandmorphness = 0;
5440 righthandmorphend = 0;
5441 targetrighthandmorphness = 1;
5444 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5445 lefthandmorphness = 0;
5446 lefthandmorphend = 0;
5447 targetlefthandmorphness = 1;
5450 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5453 targetheadmorphness = 1;
5457 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5458 //close hands and mouth
5459 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5460 righthandmorphness = 0;
5461 righthandmorphend = 1;
5462 targetrighthandmorphness = 1;
5465 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5466 lefthandmorphness = 0;
5467 lefthandmorphend = 1;
5468 targetlefthandmorphness = 1;
5471 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5474 targetheadmorphness = 1;
5478 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) {
5479 //close hands and yell
5480 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5481 righthandmorphness = 0;
5482 righthandmorphend = 1;
5483 targetrighthandmorphness = 1;
5486 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5487 lefthandmorphness = 0;
5488 lefthandmorphend = 1;
5489 targetlefthandmorphness = 1;
5492 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5495 targetheadmorphness = 1;
5502 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5503 (victim->aitype != searchtype) && (aitype != passivetype) &&
5504 (aitype != searchtype) && (victim->id < Person::players.size())) {
5505 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5509 if (!dead && animTarget != hurtidleanim)
5510 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5511 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5514 targetheadmorphness = 1;
5518 if (weaponactive != -1) {
5519 if (weapons[weaponids[weaponactive]].getType() != staff) {
5520 righthandmorphstart = 1;
5521 righthandmorphend = 1;
5523 if (weapons[weaponids[weaponactive]].getType() == staff) {
5524 righthandmorphstart = 2;
5525 righthandmorphend = 2;
5527 targetrighthandmorphness = 1;
5530 terrainnormal = terrain.getNormal(coords.x, coords.z);
5532 if (animation[animTarget].attack != reversal) {
5533 if (!isnormal(coords.x))
5541 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5542 facing = flatfacing;
5543 ReflectVector(&facing, terrainnormal);
5546 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5548 targettilt2 = -facing.y * 20;
5553 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5555 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5556 flatvelocity = velocity;
5558 flatvelspeed = findLength(&flatvelocity);
5559 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5560 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5565 if (targettilt > 25)
5567 if (targettilt < -25)
5571 if (targettilt2 > 45)
5573 if (targettilt2 < -45)
5575 if (abs(tilt2 - targettilt2) < multiplier * 400)
5576 tilt2 = targettilt2;
5577 else if (tilt2 > targettilt2) {
5578 tilt2 -= multiplier * 400;
5579 } else if (tilt2 < targettilt2) {
5580 tilt2 += multiplier * 400;
5582 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5589 if (!isnormal(targettilt) && targettilt) {
5592 if (!isnormal(targettilt2) && targettilt2) {
5597 if (animTarget == rabbittackleanim) {
5598 velocity += facing * multiplier * speed * 700 * scale;
5599 velspeed = findLength(&velocity);
5600 if (velspeed > speed * 65 * scale) {
5601 velocity /= velspeed;
5602 velspeed = speed * 65 * scale;
5603 velocity *= velspeed;
5605 velocity.y += gravity * multiplier * 20;
5606 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5607 velspeed = findLength(&velocity);
5608 velocity = flatfacing * velspeed;
5610 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5611 if (isRun() || animTarget == rabbitkickanim) {
5612 velocity += facing * multiplier * speed * 700 * scale;
5613 velspeed = findLength(&velocity);
5614 if (velspeed > speed * 45 * scale) {
5615 velocity /= velspeed;
5616 velspeed = speed * 45 * scale;
5617 velocity *= velspeed;
5619 velocity.y += gravity * multiplier * 20;
5620 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5621 velspeed = findLength(&velocity);
5622 if (velspeed < speed * 30 * scale)
5623 velspeed = speed * 30 * scale;
5624 velocity = flatfacing * velspeed;
5626 } else if (isRun()) {
5627 velocity += facing * multiplier * speed * 700 * scale;
5628 velspeed = findLength(&velocity);
5629 if (creature == rabbittype) {
5630 if (velspeed > speed * 55 * scale) {
5631 velocity /= velspeed;
5632 velspeed = speed * 55 * scale;
5633 velocity *= velspeed;
5636 if (creature == wolftype) {
5637 if (velspeed > speed * 75 * scale) {
5638 velocity /= velspeed;
5639 velspeed = speed * 75 * scale;
5640 velocity *= velspeed;
5643 velocity.y += gravity * multiplier * 20;
5644 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5645 velspeed = findLength(&velocity);
5646 velocity = flatfacing * velspeed;
5649 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5650 velocity += facing * multiplier * speed * 700 * scale;
5651 velspeed = findLength(&velocity);
5652 if (velspeed > speed * 45 * scale) {
5653 velocity /= velspeed;
5654 velspeed = speed * 45 * scale;
5655 velocity *= velspeed;
5657 velocity.y += gravity * multiplier * 20;
5658 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5659 velspeed = findLength(&velocity);
5660 velocity = flatfacing * velspeed;
5663 if (animTarget == sneakanim || animTarget == walkanim) {
5664 velocity += facing * multiplier * speed * 700 * scale;
5665 velspeed = findLength(&velocity);
5666 if (velspeed > speed * 12 * scale) {
5667 velocity /= velspeed;
5668 velspeed = speed * 12 * scale;
5669 velocity *= velspeed;
5671 velocity.y += gravity * multiplier * 20;
5672 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5673 velspeed = findLength(&velocity);
5674 velocity = flatfacing * velspeed;
5677 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5678 velocity += facing * multiplier * speed * 700 * scale;
5679 velspeed = findLength(&velocity);
5680 if (velspeed > speed * 2 * scale) {
5681 velocity /= velspeed;
5682 velspeed = speed * 2 * scale;
5683 velocity *= velspeed;
5685 velocity.y += gravity * multiplier * 20;
5686 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5687 velspeed = findLength(&velocity);
5688 velocity = flatfacing * velspeed;
5692 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5693 velocity -= facing * multiplier * speed * 700 * scale;
5694 velspeed = findLength(&velocity);
5695 if (velspeed > speed * 2 * scale) {
5696 velocity /= velspeed;
5697 velspeed = speed * 2 * scale;
5698 velocity *= velspeed;
5700 velocity.y += gravity * multiplier * 20;
5701 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5702 velspeed = findLength(&velocity);
5703 velocity = flatfacing * velspeed * -1;
5706 if (animTarget == fightsidestep) {
5707 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5708 velspeed = findLength(&velocity);
5709 if (velspeed > speed * 12 * scale) {
5710 velocity /= velspeed;
5711 velspeed = speed * 12 * scale;
5712 velocity *= velspeed;
5714 velocity.y += gravity * multiplier * 20;
5715 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5716 velspeed = findLength(&velocity);
5717 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5720 if (animTarget == staggerbackhighanim) {
5721 coords -= facing * multiplier * speed * 16 * scale;
5724 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5725 coords -= facing * multiplier * speed * 20 * scale;
5729 if (animTarget == backhandspringanim) {
5730 //coords-=facing*multiplier*50*scale;
5731 velocity += facing * multiplier * speed * 700 * scale * -1;
5732 velspeed = findLength(&velocity);
5733 if (velspeed > speed * 50 * scale) {
5734 velocity /= velspeed;
5735 velspeed = speed * 50 * scale;
5736 velocity *= velspeed;
5738 velocity.y += gravity * multiplier * 20;
5739 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5740 velspeed = findLength(&velocity);
5741 velocity = flatfacing * velspeed * -1;
5743 if (animTarget == dodgebackanim) {
5744 //coords-=facing*multiplier*50*scale;
5745 velocity += facing * multiplier * speed * 700 * scale * -1;
5746 velspeed = findLength(&velocity);
5747 if (velspeed > speed * 60 * scale) {
5748 velocity /= velspeed;
5749 velspeed = speed * 60 * scale;
5750 velocity *= velspeed;
5752 velocity.y += gravity * multiplier * 20;
5753 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5754 velspeed = findLength(&velocity);
5755 velocity = flatfacing * velspeed * -1;
5758 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5759 velspeed = findLength(&velocity);
5763 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5764 velocity.y += gravity * multiplier;
5767 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5768 coords += velocity * multiplier;
5770 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5771 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5774 if (animTarget == jumpupanim) {
5776 animTarget = getIdle();
5783 pause_sound(whooshsound);
5784 OPENAL_SetVolume(channels[whooshsound], 0);
5787 if (animTarget == jumpdownanim || isFlip()) {
5788 if (isFlip())jumppower = -4;
5789 animTarget = getLanding();
5790 emit_sound_at(landsound, coords, 128.);
5793 envsound[numenvsounds] = coords;
5794 envsoundvol[numenvsounds] = 16;
5795 envsoundlife[numenvsounds] = .4;
5801 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5802 coords.y += gravity * multiplier * 2;
5803 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5804 coords.y = terrain.getHeight(coords.x, coords.z);
5809 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)) {
5810 velspeed = findLength(&velocity);
5812 if (velspeed < multiplier * 300 * scale) {
5815 velocity -= velocity / velspeed * multiplier * 300 * scale;
5816 if (velspeed > 5 && (isLanding() || isLandhard())) {
5817 skiddingdelay += multiplier;
5818 if (skiddelay <= 0) {
5828 velspeed = findLength(&velocity);
5830 if (velspeed < multiplier * 600 * scale) {
5833 velocity -= velocity / velspeed * multiplier * 600 * scale;
5835 if (velspeed > 5 && (isLanding() || isLandhard())) {
5836 skiddingdelay += multiplier;
5837 if (skiddelay <= 0) {
5846 if (skiddingdelay < 0)
5847 skiddingdelay += multiplier;
5848 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5850 if (!onterrain || environment == grassyenvironment) {
5851 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5853 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5857 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5858 terrainnormal = victim->coords - coords;
5859 Normalise(&terrainnormal);
5860 targetyaw = -asin(0 - terrainnormal.x);
5861 targetyaw *= 360 / 6.28;
5862 if (terrainnormal.z < 0)
5863 targetyaw = 180 - targetyaw;
5864 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5867 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5868 targetyaw = victim->targetyaw;
5870 if (animTarget == rabbittacklinganim) {
5871 coords = victim->coords;
5874 skeleton.oldfree = skeleton.free;
5878 midterrain.x = terrain.size * terrain.scale / 2;
5879 midterrain.z = terrain.size * terrain.scale / 2;
5880 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5882 tempposit = coords - midterrain;
5884 Normalise(&tempposit);
5885 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5886 coords.x = tempposit.x + midterrain.x;
5887 coords.z = tempposit.z + midterrain.z;
5893 * inverse kinematics helper function
5895 void IKHelper(Person *p, float interp)
5897 XYZ point, change, change2;
5898 float heightleft, heightright;
5900 // TODO: implement localToWorld and worldToLocal
5901 // but keep in mind it won't be the same math if player is ragdolled or something
5902 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5903 // then comb through code for places where to use it
5905 // point = localToWorld(jointPos(leftfoot))
5906 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5907 // adjust height of foot
5908 heightleft = terrain.getHeight(point.x, point.z) + .04;
5909 point.y = heightleft;
5910 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5911 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5912 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5913 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5914 // move ankle along with foot
5915 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5916 // average knee pos between old and new pos
5917 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5919 // do same as above for right leg
5920 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5921 heightright = terrain.getHeight(point.x, point.z) + .04;
5922 point.y = heightright;
5923 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5924 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5925 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5926 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5927 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5929 // fix up skeleton now that we've moved body parts?
5930 p->skeleton.DoConstraints(&p->coords, &p->scale);
5937 int Person::DrawSkeleton()
5939 int oldplayerdetail;
5940 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5941 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5951 glAlphaFunc(GL_GREATER, 0.0001);
5953 float terrainheight;
5957 if (!isnormal(tilt))
5959 if (!isnormal(tilt2))
5961 oldplayerdetail = playerdetail;
5963 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5966 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5969 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5974 if (playerdetail != oldplayerdetail) {
5976 normalsupdatedelay = 0;
5978 static float updatedelaychange;
5979 static float morphness;
5980 static float framemult;
5982 skeleton.FindForwards();
5983 if (howactive == typesittingwall) {
5984 skeleton.specialforward[1] = 0;
5985 skeleton.specialforward[1].z = 1;
5991 static int weaponattachmuscle;
5992 static int weaponrotatemuscle;
5993 static XYZ weaponpoint;
5994 static int start, endthing;
5995 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5996 if (!isSleeping() && !isSitting()) {
5997 // TODO: give these meaningful names
5998 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5999 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6000 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6001 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6003 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6005 if (creature == wolftype)
6009 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6010 IKHelper(this, target);
6011 if (creature == wolftype)
6012 IKHelper(this, target);
6015 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6016 IKHelper(this, 1 - target);
6017 if (creature == wolftype)
6018 IKHelper(this, 1 - target);
6022 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()))
6025 targetheadyaw = -targetyaw;
6026 targetheadpitch = 0;
6027 if (animation[animTarget].attack == 3)
6028 targetheadyaw += 180;
6030 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6031 skeleton.drawmodel.vertex[i] = 0;
6032 skeleton.drawmodel.vertex[i].y = 999;
6034 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6035 skeleton.drawmodellow.vertex[i] = 0;
6036 skeleton.drawmodellow.vertex[i].y = 999;
6038 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6039 skeleton.drawmodelclothes.vertex[i] = 0;
6040 skeleton.drawmodelclothes.vertex[i].y = 999;
6042 for (int i = 0; i < skeleton.num_muscles; i++) {
6043 // convenience renames
6044 const int p1 = skeleton.muscles[i].parent1->label;
6045 const int p2 = skeleton.muscles[i].parent2->label;
6047 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6052 if (p1 == righthand || p2 == righthand) {
6053 morphness = righthandmorphness;
6054 start = righthandmorphstart;
6055 endthing = righthandmorphend;
6057 if (p1 == lefthand || p2 == lefthand) {
6058 morphness = lefthandmorphness;
6059 start = lefthandmorphstart;
6060 endthing = lefthandmorphend;
6062 if (p1 == head || p2 == head) {
6063 morphness = headmorphness;
6064 start = headmorphstart;
6065 endthing = headmorphend;
6067 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6068 morphness = chestmorphness;
6069 start = chestmorphstart;
6070 endthing = chestmorphend;
6072 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6073 morphness = tailmorphness;
6074 start = tailmorphstart;
6075 endthing = tailmorphend;
6078 skeleton.FindRotationMuscle(i, animTarget);
6079 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6080 glMatrixMode(GL_MODELVIEW);
6084 glRotatef(tilt2, 1, 0, 0);
6086 glRotatef(tilt, 0, 0, 1);
6089 glTranslatef(mid.x, mid.y, mid.z);
6091 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6092 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6094 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6095 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6097 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6098 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6100 if (playerdetail || skeleton.free == 3) {
6101 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6102 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6103 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6104 glMatrixMode(GL_MODELVIEW);
6106 if (p1 == abdomen || p2 == abdomen)
6107 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6108 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6109 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6110 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6111 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6112 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6113 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6114 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6115 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6116 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6117 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6118 if (p1 == head || p2 == head)
6119 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6120 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6121 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6122 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6123 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6124 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6125 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6129 if (!playerdetail || skeleton.free == 3) {
6130 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6131 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6132 glMatrixMode(GL_MODELVIEW);
6134 if (p1 == abdomen || p2 == abdomen)
6135 glTranslatef(v0.x * proportionbody.x,
6136 v0.y * proportionbody.y,
6137 v0.z * proportionbody.z);
6138 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6139 glTranslatef(v0.x * proportionarms.x,
6140 v0.y * proportionarms.y,
6141 v0.z * proportionarms.z);
6142 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6143 glTranslatef(v0.x * proportionlegs.x,
6144 v0.y * proportionlegs.y,
6145 v0.z * proportionlegs.z);
6146 if (p1 == head || p2 == head)
6147 glTranslatef(v0.x * proportionhead.x,
6148 v0.y * proportionhead.y,
6149 v0.z * proportionhead.z);
6151 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6152 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6153 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6154 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6160 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6161 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6163 glMatrixMode(GL_MODELVIEW);
6167 glRotatef(tilt2, 1, 0, 0);
6169 glRotatef(tilt, 0, 0, 1);
6170 glTranslatef(mid.x, mid.y, mid.z);
6171 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6172 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6174 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6175 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6177 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6178 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6180 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6181 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6182 glMatrixMode(GL_MODELVIEW);
6184 if (p1 == abdomen || p2 == abdomen)
6185 glTranslatef(v0.x * proportionbody.x,
6186 v0.y * proportionbody.y,
6187 v0.z * proportionbody.z);
6188 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6189 glTranslatef(v0.x * proportionarms.x,
6190 v0.y * proportionarms.y,
6191 v0.z * proportionarms.z);
6192 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6193 glTranslatef(v0.x * proportionlegs.x,
6194 v0.y * proportionlegs.y,
6195 v0.z * proportionlegs.z);
6196 if (p1 == head || p2 == head)
6197 glTranslatef(v0.x * proportionhead.x,
6198 v0.y * proportionhead.y,
6199 v0.z * proportionhead.z);
6200 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6201 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6202 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6203 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6208 updatedelay = 1 + (float)(Random() % 100) / 1000;
6210 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6211 normalsupdatedelay = 1;
6212 if (playerdetail || skeleton.free == 3)
6213 skeleton.drawmodel.CalculateNormals(0);
6214 if (!playerdetail || skeleton.free == 3)
6215 skeleton.drawmodellow.CalculateNormals(0);
6216 if (skeleton.clothes)
6217 skeleton.drawmodelclothes.CalculateNormals(0);
6219 if (playerdetail || skeleton.free == 3)
6220 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6221 if (!playerdetail || skeleton.free == 3)
6222 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6223 if (skeleton.clothes) {
6224 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6229 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6230 if (updatedelaychange > -realmultiplier * 30)
6231 updatedelaychange = -realmultiplier * 30;
6232 if (updatedelaychange > -framemult * 4)
6233 updatedelaychange = -framemult * 4;
6234 if (skeleton.free == 1)
6235 updatedelaychange *= 6;
6237 updatedelaychange *= 8;
6238 updatedelay += updatedelaychange;
6240 glMatrixMode(GL_MODELVIEW);
6242 glTranslatef(coords.x, coords.y - .02, coords.z);
6243 if (!skeleton.free) {
6244 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6245 glRotatef(yaw, 0, 1, 0);
6249 glColor4f(.4, 1, .4, 1);
6250 glDisable(GL_LIGHTING);
6251 glDisable(GL_TEXTURE_2D);
6254 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6255 XYZ &v0 = skeleton.drawmodel.vertex[i];
6256 glVertex3f(v0.x, v0.y, v0.z);
6262 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6263 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6264 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6265 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6266 glVertex3f(v0.x, v0.y, v0.z);
6267 glVertex3f(v1.x, v1.y, v1.z);
6268 glVertex3f(v1.x, v1.y, v1.z);
6269 glVertex3f(v2.x, v2.y, v2.z);
6270 glVertex3f(v2.x, v2.y, v2.z);
6271 glVertex3f(v0.x, v0.y, v0.z);
6277 terrainlight = terrain.getLighting(coords.x, coords.z);
6278 distance = distsq(&viewer, &coords);
6279 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6283 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6284 if (terrainheight < 1)
6286 if (terrainheight > 1.7)
6287 terrainheight = 1.7;
6290 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6291 glDisable(GL_BLEND);
6292 glAlphaFunc(GL_GREATER, 0.0001);
6293 glEnable(GL_TEXTURE_2D);
6295 glDisable(GL_TEXTURE_2D);
6296 glColor4f(.7, .35, 0, .5);
6298 glEnable(GL_LIGHTING);
6301 if (tutoriallevel && id != 0) {
6302 glColor4f(.7, .7, .7, 0.6);
6304 glEnable(GL_LIGHTING);
6306 if (canattack && cananger)
6307 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6308 glDisable(GL_TEXTURE_2D);
6309 glColor4f(1, 0, 0, 0.8);
6311 glMatrixMode(GL_TEXTURE);
6313 glTranslatef(0, -smoketex, 0);
6314 glTranslatef(-smoketex, 0, 0);
6318 if ((tutoriallevel && id != 0))
6319 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6321 skeleton.drawmodel.draw();
6324 if (!playerdetail) {
6325 if ((tutoriallevel && id != 0))
6326 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6328 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6331 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6332 if (tutoriallevel && id != 0) {
6334 glMatrixMode(GL_MODELVIEW);
6335 glEnable(GL_TEXTURE_2D);
6336 glColor4f(.7, .7, .7, 0.6);
6338 glEnable(GL_LIGHTING);
6340 if (canattack && cananger)
6341 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6342 glDisable(GL_TEXTURE_2D);
6343 glColor4f(1, 0, 0, 0.8);
6345 glMatrixMode(GL_TEXTURE);
6347 glTranslatef(0, -smoketex * .6, 0);
6348 glTranslatef(smoketex * .6, 0, 0);
6351 if ((tutoriallevel && id != 0))
6352 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6354 skeleton.drawmodel.draw();
6357 if (!playerdetail) {
6358 if ((tutoriallevel && id != 0))
6359 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6361 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6366 if (tutoriallevel && id != 0) {
6368 glMatrixMode(GL_MODELVIEW);
6369 glEnable(GL_TEXTURE_2D);
6371 if (skeleton.clothes) {
6375 skeleton.drawmodelclothes.draw();
6377 skeleton.drawmodelclothes.drawimmediate();
6383 if (num_weapons > 0) {
6384 for (k = 0; k < num_weapons; k++) {
6386 if (weaponactive == k) {
6387 if (weapons[i].getType() != staff) {
6388 for (j = 0; j < skeleton.num_muscles; j++) {
6389 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6390 weaponattachmuscle = j;
6393 for (j = 0; j < skeleton.num_muscles; j++) {
6394 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) {
6395 weaponrotatemuscle = j;
6398 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6399 if (creature == wolftype)
6400 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6402 if (weapons[i].getType() == staff) {
6403 for (j = 0; j < skeleton.num_muscles; j++) {
6404 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6405 weaponattachmuscle = j;
6408 for (j = 0; j < skeleton.num_muscles; j++) {
6409 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) {
6410 weaponrotatemuscle = j;
6413 //weaponpoint=jointPos(rightwrist);
6414 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6415 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6416 XYZ tempnormthing, vec1, vec2;
6417 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6418 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6419 CrossProduct(&vec1, &vec2, &tempnormthing);
6420 Normalise(&tempnormthing);
6421 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6422 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6425 if (weaponactive != k && weaponstuck != k) {
6426 if (weapons[i].getType() == knife)
6427 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6428 if (weapons[i].getType() == sword)
6429 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6430 if (weapons[i].getType() == staff)
6431 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6432 for (j = 0; j < skeleton.num_muscles; j++) {
6433 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) {
6434 weaponrotatemuscle = j;
6438 if (weaponstuck == k) {
6439 if (weaponstuckwhere == 0)
6440 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6442 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6443 for (j = 0; j < skeleton.num_muscles; j++) {
6444 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) {
6445 weaponrotatemuscle = j;
6449 if (skeleton.free) {
6450 weapons[i].position = weaponpoint * scale + coords;
6451 weapons[i].bigrotation = 0;
6452 weapons[i].bigtilt = 0;
6453 weapons[i].bigtilt2 = 0;
6455 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;
6456 weapons[i].bigrotation = yaw;
6457 weapons[i].bigtilt = tilt;
6458 weapons[i].bigtilt2 = tilt2;
6460 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6461 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6462 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6463 if (weaponactive == k) {
6464 if (weapons[i].getType() == knife) {
6465 weapons[i].smallrotation = 180;
6466 weapons[i].smallrotation2 = 0;
6467 if (isCrouch() || wasCrouch()) {
6468 weapons[i].smallrotation2 = 20;
6470 if (animTarget == hurtidleanim) {
6471 weapons[i].smallrotation2 = 50;
6473 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6474 XYZ temppoint1, temppoint2;
6477 temppoint1 = jointPos(righthand);
6478 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6479 distance = findDistance(&temppoint1, &temppoint2);
6480 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6481 weapons[i].rotation2 *= 360 / 6.28;
6484 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6485 weapons[i].rotation1 *= 360 / 6.28;
6486 weapons[i].rotation3 = 0;
6487 weapons[i].smallrotation = -90;
6488 weapons[i].smallrotation2 = 0;
6489 if (temppoint1.x > temppoint2.x)
6490 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6492 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
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 (animTarget == knifethrowanim) {
6512 weapons[i].smallrotation = 90;
6513 //weapons[i].smallrotation2=-90;
6514 weapons[i].smallrotation2 = 0;
6515 weapons[i].rotation1 = 0;
6516 weapons[i].rotation2 = 0;
6517 weapons[i].rotation3 = 0;
6519 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6520 weapons[i].smallrotation = -90;
6521 weapons[i].rotation1 = 0;
6522 weapons[i].rotation2 = 0;
6523 weapons[i].rotation3 = 0;
6526 if (weapons[i].getType() == sword) {
6527 weapons[i].smallrotation = 0;
6528 weapons[i].smallrotation2 = 0;
6529 if (animTarget == knifethrowanim) {
6530 weapons[i].smallrotation = -90;
6531 weapons[i].smallrotation2 = 0;
6532 weapons[i].rotation1 = 0;
6533 weapons[i].rotation2 = 0;
6534 weapons[i].rotation3 = 0;
6536 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)) {
6537 XYZ temppoint1, temppoint2;
6540 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6541 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6542 distance = findDistance(&temppoint1, &temppoint2);
6543 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6544 weapons[i].rotation2 *= 360 / 6.28;
6547 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6548 weapons[i].rotation1 *= 360 / 6.28;
6549 weapons[i].rotation3 = 0;
6550 weapons[i].smallrotation = 90;
6551 weapons[i].smallrotation2 = 0;
6552 if (temppoint1.x > temppoint2.x)
6553 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6556 if (weapons[i].getType() == staff) {
6557 weapons[i].smallrotation = 100;
6558 weapons[i].smallrotation2 = 0;
6559 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6560 XYZ temppoint1, temppoint2;
6563 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6564 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6565 distance = findDistance(&temppoint1, &temppoint2);
6566 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6567 weapons[i].rotation2 *= 360 / 6.28;
6570 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6571 weapons[i].rotation1 *= 360 / 6.28;
6572 weapons[i].rotation3 = 0;
6573 weapons[i].smallrotation = 90;
6574 weapons[i].smallrotation2 = 0;
6575 if (temppoint1.x > temppoint2.x)
6576 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6580 if (weaponactive != k && weaponstuck != k) {
6581 if (weapons[i].getType() == knife) {
6582 weapons[i].smallrotation = -70;
6583 weapons[i].smallrotation2 = 10;
6585 if (weapons[i].getType() == sword) {
6586 weapons[i].smallrotation = -100;
6587 weapons[i].smallrotation2 = -8;
6589 if (weapons[i].getType() == staff) {
6590 weapons[i].smallrotation = -100;
6591 weapons[i].smallrotation2 = -8;
6594 if (weaponstuck == k) {
6595 if (weaponstuckwhere == 0)
6596 weapons[i].smallrotation = 180;
6598 weapons[i].smallrotation = 0;
6599 weapons[i].smallrotation2 = 10;
6608 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6610 if (animCurrent != animTarget)
6612 if (skeleton.free == 2)
6621 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6624 static float distance;
6625 static float olddistance;
6626 static int intersecting;
6627 static int firstintersecting;
6630 static XYZ start, end;
6631 static float slopethreshold = -.4;
6633 firstintersecting = -1;
6637 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6640 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6641 for (i = 0; i < 4; i++) {
6642 for (j = 0; j < model->TriangleNum; j++) {
6643 if (model->facenormals[j].y <= slopethreshold) {
6645 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)));
6646 if (distance < radius) {
6647 point = *p1 - model->facenormals[j] * distance;
6648 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]]))
6651 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6652 &model->vertex[model->Triangles[j].vertex[1]],
6655 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6656 &model->vertex[model->Triangles[j].vertex[2]],
6659 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6660 &model->vertex[model->Triangles[j].vertex[2]],
6663 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6667 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)) {
6668 p1->y = point.y + radius;
6669 if ((animTarget == jumpdownanim || isFlip())) {
6670 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6673 if (animTarget == jumpupanim) {
6675 animTarget = getIdle();
6682 pause_sound(whooshsound);
6683 OPENAL_SetVolume(channels[whooshsound], 0);
6686 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6689 animTarget = getLanding();
6690 emit_sound_at(landsound, coords, 128.);
6693 envsound[numenvsounds] = coords;
6694 envsoundvol[numenvsounds] = 16;
6695 envsoundlife[numenvsounds] = .4;
6703 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6704 olddistance = distance;
6705 firstintersecting = j;
6710 for (j = 0; j < model->TriangleNum; j++) {
6711 if (model->facenormals[j].y > slopethreshold) {
6714 start.y -= radius / 4;
6715 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6716 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6717 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6718 distance = abs((model->facenormals[j].x * start.x)
6719 + (model->facenormals[j].y * start.y)
6720 + (model->facenormals[j].z * start.z)
6721 - ((model->facenormals[j].x * v0.x)
6722 + (model->facenormals[j].y * v0.y)
6723 + (model->facenormals[j].z * v0.z)));
6724 if (distance < radius * .5) {
6725 point = start - model->facenormals[j] * distance;
6726 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6729 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6731 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6733 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6735 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6736 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6738 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6739 if (findLengthfast(&start) < findLengthfast(&velocity))
6742 *p1 += model->facenormals[j] * (distance - radius * .5);
6745 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6746 olddistance = distance;
6747 firstintersecting = j;
6754 *p = DoRotation(*p, 0, *rotate, 0);
6757 *p1 = DoRotation(*p1, 0, *rotate, 0);
6759 return firstintersecting;
6762 void Person::takeWeapon(int weaponId)
6765 weapons[weaponId].owner = id;
6766 if (num_weapons > 0) {
6767 weaponids[num_weapons] = weaponids[0];
6770 weaponids[0] = weaponId;
6773 void Person::addClothes()
6775 if (numclothes > 0) {
6776 for (int i = 0; i < numclothes; i++) {
6783 bool Person::addClothes(const int& clothesId)
6786 const char* fileName = clothes[clothesId];
6788 GLubyte* array = &skeleton.skinText[0];
6792 bool opened = load_image(fileName, texture);
6797 float tintr = clothestintr[clothesId];
6798 float tintg = clothestintg[clothesId];
6799 float tintb = clothestintb[clothesId];
6801 if (tintr > 1) tintr = 1;
6802 if (tintg > 1) tintg = 1;
6803 if (tintb > 1) tintb = 1;
6805 if (tintr < 0) tintr = 0;
6806 if (tintg < 0) tintg = 0;
6807 if (tintb < 0) tintb = 0;
6809 int bytesPerPixel = texture.bpp / 8;
6813 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6814 if (bytesPerPixel == 3)
6816 else if ((i + 1) % 4 == 0)
6817 alphanum = texture.data[i];
6818 if ((i + 1) % 4 || bytesPerPixel == 3) {
6820 texture.data[i] *= tintr;
6822 texture.data[i] *= tintg;
6824 texture.data[i] *= tintb;
6825 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);