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;
60 extern XYZ envsound[30];
61 extern float envsoundvol[30];
62 extern float envsoundlife[30];
63 extern int numenvsounds;
64 extern int tutoriallevel;
65 extern float smoketex;
66 extern int tutorialstage;
67 extern bool reversaltrain;
68 extern bool canattack;
70 extern float damagedealt;
72 extern float hostiletime;
74 extern int indialogue;
76 extern bool gamestarted;
78 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
91 howactive(typeactive),
93 superruntoggle(false),
94 lastattack(0), lastattack2(0), lastattack3(0),
95 currentoffset(), targetoffset(), offset(),
127 rabbitkickenabled(false),
139 superpermanentdamage(0),
153 bleedx(0), bleedy(0),
157 headyaw(0), headpitch(0),
158 targetheadyaw(0), targetheadpitch(0),
169 normalsupdatedelay(0),
172 forwardkeydown(false),
173 forwardstogglekeydown(false),
178 jumptogglekeydown(false),
179 crouchkeydown(false),
180 crouchtogglekeydown(false),
182 drawtogglekeydown(false),
184 throwtogglekeydown(false),
185 attackkeydown(false),
190 crouchkeydowntime(0),
204 whichdirection(false),
205 whichdirectiondelay(0),
206 avoidsomething(false),
215 lefthandmorphness(0),
216 righthandmorphness(0),
220 targetlefthandmorphness(0),
221 targetrighthandmorphness(0),
222 targetheadmorphness(0),
223 targetchestmorphness(0),
224 targettailmorphness(0),
225 lefthandmorphstart(0), lefthandmorphend(0),
226 righthandmorphstart(0), righthandmorphend(0),
227 headmorphstart(0), headmorphend(0),
228 chestmorphstart(0), chestmorphend(0),
229 tailmorphstart(0), tailmorphend(0),
232 highreversaldelay(0),
235 creature(rabbittype),
282 finalpathfindpoint(0),
283 targetpathfindpoint(0),
284 lastpathfindpoint(0),
285 lastpathfindpoint2(0),
286 lastpathfindpoint3(0),
287 lastpathfindpoint4(0),
303 neckspurtparticledelay(0),
307 rabbitkickragdoll(false),
320 * GameTick/doPlayerCollisions
322 void Person::CheckKick()
325 && (animTarget == rabbitkickanim
327 && victim != this->shared_from_this()
329 && animCurrent == rabbitkickanim)
330 && distsq(&coords, &victim->coords) < 1.2
331 && !victim->skeleton.free))
334 if (animation[victim->animTarget].height != lowheight) {
335 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
336 XYZ relative = velocity;
338 Normalise(&relative);
342 if (tutoriallevel != 1)
343 emit_sound_at(heavyimpactsound, victim->coords);
345 for (int i = 0; i < victim->skeleton.num_joints; i++) {
346 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
349 victim->DoDamage(100 * damagemult / victim->protectionhigh);
355 animTarget = backflipanim;
357 velocity = facing * -10;
361 resume_stream(whooshsound);
363 award_bonus(id, cannon);
364 } else if (victim->isCrouch()) {
365 animTarget = rabbitkickreversedanim;
366 animCurrent = rabbitkickreversedanim;
367 victim->animCurrent = rabbitkickreversalanim;
368 victim->animTarget = rabbitkickreversalanim;
374 victim->oldcoords = victim->coords;
375 coords = victim->coords;
376 victim->targetyaw = targetyaw;
377 victim->victim = this->shared_from_this();
384 * GameTick/doPlayerCollisions - spread fire between players
385 * GameTick/doDebugKeys - press f to ignite
386 * Person::DoStuff - spread fire from lit campfires and bushes
388 void Person::CatchFire()
390 XYZ flatfacing, flatvelocity;
392 for (int i = 0; i < 10; i++) {
393 howmany = abs(Random() % (skeleton.num_joints));
395 flatvelocity = skeleton.joints[howmany].velocity;
396 flatfacing = skeleton.joints[howmany].position * scale + coords;
398 flatvelocity = velocity;
399 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
401 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
406 emit_sound_at(firestartsound, coords);
408 emit_stream_at(stream_firesound, coords);
416 * idle animation for this creature (depending on status)
418 int Person::getIdle()
420 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
422 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
423 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
424 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
425 victim->id < Person::players.size())) {
426 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
427 if (creature == rabbittype)
428 return fightidleanim;
429 if (creature == wolftype)
432 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
433 if (weapons[weaponids[weaponactive]].getType() == knife)
434 return knifefightidleanim;
435 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
436 return swordfightidlebothanim;
437 if (weapons[weaponids[weaponactive]].getType() == sword)
438 return swordfightidleanim;
439 if (weapons[weaponids[weaponactive]].getType() == staff)
440 return swordfightidleanim;
442 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
443 return fightsidestep;
445 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
447 if (howactive == typesitting) return sitanim;
448 if (howactive == typesittingwall) return sitwallanim;
449 if (howactive == typesleeping) return sleepanim;
450 if (howactive == typedead1) return dead1anim;
451 if (howactive == typedead2) return dead2anim;
452 if (howactive == typedead3) return dead3anim;
453 if (howactive == typedead4) return dead4anim;
454 if (creature == rabbittype) return bounceidleanim;
455 if (creature == wolftype) return wolfidle;
460 * crouch animation for this creature
462 int Person::getCrouch()
464 if (creature == rabbittype)
466 if (creature == wolftype)
467 return wolfcrouchanim;
472 * running animation for this creature (can be upright or all fours)
476 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
478 if (creature == wolftype && (!superruntoggle))
481 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
482 return rabbitrunninganim;
483 if (creature == wolftype && (superruntoggle))
484 return wolfrunninganim;
490 int Person::getStop()
492 if (creature == rabbittype)
494 if (creature == wolftype)
501 int Person::getLanding()
503 if (creature == rabbittype)
505 if (creature == wolftype)
512 int Person::getLandhard()
514 if (creature == rabbittype)
516 if (creature == wolftype)
517 return wolflandhardanim;
524 * Person::DoAnimations
527 SolidHitBonus(int playerid)
529 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
530 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
532 award_bonus(playerid, solidhit);
536 * spawns blood effects
538 void Person::DoBlood(float howmuch, int which)
540 // FIXME: should abstract out inputs
541 static int bleedxint, bleedyint;
543 if (bloodtoggle && tutoriallevel != 1) {
544 if (bleeding <= 0 && spurt) {
546 for (int i = 0; i < 3; i++) {
547 // emit blood particles
550 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
551 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
552 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
553 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
556 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
557 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
558 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
559 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
562 if (Random() % 2 == 0) // 50% chance
563 for (int i = 0; i < 3; i++) {
564 if (Random() % 2 != 0) {
565 // emit teeth particles
568 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
569 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
572 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
573 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
577 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
579 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
581 Sprite::setLastSpriteSpecial(3); // sets it to teeth
586 // FIXME: manipulating attributes
587 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
590 if (creature == rabbittype)
591 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) {
592 bleedxint = abs(Random() % 512);
593 bleedyint = abs(Random() % 512);
595 if (creature == wolftype)
596 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) {
597 bleedxint = abs(Random() % 512);
598 bleedyint = abs(Random() % 512);
602 bleedy /= realtexdetail;
603 bleedx /= realtexdetail;
604 direction = abs(Random() % 2) * 2 - 1;
613 * spawns big blood effects and ???
614 * modifies character's skin texture
616 void Person::DoBloodBig(float howmuch, int which)
618 static int bleedxint, bleedyint, i, j;
620 if (howmuch && id == 0)
623 if (tutoriallevel != 1 || id == 0)
624 if (aitype != playercontrolled && howmuch > 0) {
628 // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
629 if (creature == wolftype) {
630 int i = abs(Random() % 2);
632 whichsound = snarlsound;
634 whichsound = snarl2sound;
635 envsound[numenvsounds] = coords;
636 envsoundvol[numenvsounds] = 16;
637 envsoundlife[numenvsounds] = .4;
640 if (creature == rabbittype) {
641 int i = abs(Random() % 2);
643 whichsound = rabbitpainsound;
644 if (i == 1 && howmuch >= 2)
645 whichsound = rabbitpain1sound;
646 envsound[numenvsounds] = coords;
647 envsoundvol[numenvsounds] = 16;
648 envsoundlife[numenvsounds] = .4;
652 if (whichsound != -1)
653 emit_sound_at(whichsound, coords);
656 if (id == 0 && howmuch > 0) {
657 // FIXME: manipulating attributes
665 if (bloodtoggle && decals && tutoriallevel != 1) {
666 if (bleeding <= 0 && spurt) {
668 for (int i = 0; i < 3; i++) {
669 // emit blood particles
670 // FIXME: copypaste from above
673 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
674 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
675 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
676 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
679 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
680 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
681 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
682 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
687 // weird texture manipulation code follows.
688 // looks like this is painting blood onto the character's skin texture
689 // FIXME: surely there's a better way
691 int offsetx = 0, offsety = 0;
693 offsety = Random() % 40;
694 offsetx = abs(Random() % 60);
696 if (which == 190 || which == 185) {
697 offsety = Random() % 40;
698 offsetx = abs(Random() % 100) - 20;
701 offsety = Random() % 10;
702 offsetx = Random() % 10;
705 offsety = Random() % 20;
706 offsetx = Random() % 20;
708 if (which == 220 || which == 215) {
718 if (creature == rabbittype)
719 for (i = 0; i < 512; i++) {
720 for (j = 0; j < 512; j++) {
721 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
722 if (i < startx) startx = i;
723 if (j < starty) starty = j;
724 if (i > endx) endx = i;
725 if (j > endy) endy = j;
729 if (creature == wolftype)
730 for (i = 0; i < 512; i++) {
731 for (j = 0; j < 512; j++) {
732 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
733 if (i < startx) startx = i;
734 if (j < starty) starty = j;
735 if (i > endx) endx = i;
736 if (j > endy) endy = j;
746 if (startx < 0) startx = 0;
747 if (starty < 0) starty = 0;
748 if (endx > 512 - 1) endx = 512 - 1;
749 if (endy > 512 - 1) endy = 512 - 1;
750 if (endx < startx) endx = startx;
751 if (endy < starty) endy = starty;
753 startx /= realtexdetail;
754 starty /= realtexdetail;
755 endx /= realtexdetail;
756 endy /= realtexdetail;
758 int texdetailint = realtexdetail;
760 if (creature == rabbittype)
761 for (i = startx; i < endx; i++) {
762 for (j = starty; j < endy; j++) {
763 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) {
764 color = Random() % 85 + 170;
765 where = i * skeleton.skinsize * 3 + j * 3;
766 if (skeleton.skinText[where + 0] > color / 2)
767 skeleton.skinText[where + 0] = color / 2;
768 skeleton.skinText[where + 1] = 0;
769 skeleton.skinText[where + 2] = 0;
773 if (creature == wolftype)
774 for (i = startx; i < endx; i++) {
775 for (j = starty; j < endy; j++) {
776 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) {
777 color = Random() % 85 + 170;
778 where = i * skeleton.skinsize * 3 + j * 3;
779 if (skeleton.skinText[where + 0] > color / 2)
780 skeleton.skinText[where + 0] = color / 2;
781 skeleton.skinText[where + 1] = 0;
782 skeleton.skinText[where + 2] = 0;
786 skeleton.drawmodel.textureptr.bind();
791 if (creature == rabbittype)
792 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) {
793 bleedxint = abs(Random() % 512);
794 bleedyint = abs(Random() % 512);
796 if (creature == wolftype)
797 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) {
798 bleedxint = abs(Random() % 512);
799 bleedyint = abs(Random() % 512);
801 bleedy = bleedxint + offsetx;
802 bleedx = bleedyint + offsety;
803 bleedy /= realtexdetail;
804 bleedx /= realtexdetail;
809 if (bleedx > skeleton.skinsize - 1)
810 bleedx = skeleton.skinsize - 1;
811 if (bleedy > skeleton.skinsize - 1)
812 bleedy = skeleton.skinsize - 1;
813 direction = abs(Random() % 2) * 2 - 1;
816 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
817 deathbleeding += bleeding;
818 bloodloss += bleeding * 3;
820 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
821 if (abs(Random() % 2) == 0) {
822 aitype = gethelptype;
825 aitype = attacktypecutoff;
833 * similar to DoBloodBig
835 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
839 static XYZ startpoint, endpoint, colpoint, movepoint;
840 static float rotationpoint;
842 static XYZ p1, p2, p3, p0;
845 float coordsx, coordsy;
848 if (bloodtoggle && decals && tutoriallevel != 1) {
851 where = DoRotation(where, 0, -yaw, 0);
859 // ray testing for a tri in the character model
860 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
861 if (whichtri != -1) {
862 // low level geometry math
864 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
865 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
866 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
868 bary.x = distsq(&p0, &p1);
869 bary.y = distsq(&p0, &p2);
870 bary.z = distsq(&p0, &p3);
872 total = bary.x + bary.y + bary.z;
881 total = bary.x + bary.y + bary.z;
887 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
888 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
889 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
890 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
891 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
892 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
893 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;
894 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;
896 if (bleeding <= 0 && spurt) {
898 for (int i = 0; i < 3; i++) {
899 // emit blood particles
900 // FIXME: more copypaste code
903 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
904 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
905 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
906 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
909 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
910 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
911 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
912 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
917 // texture manipulation follows
919 int offsetx = 0, offsety = 0;
920 offsetx = (1 + coordsy) * 512 - 291;
921 offsety = coordsx * 512 - 437;
928 if (creature == rabbittype)
929 for (i = 0; i < 512; i++) {
930 for (j = 0; j < 512; j++) {
931 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
932 if (i < startx) startx = i;
933 if (j < starty) starty = j;
934 if (i > endx) endx = i;
935 if (j > endy) endy = j;
939 if (creature == wolftype)
940 for (i = 0; i < 512; i++) {
941 for (j = 0; j < 512; j++) {
942 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
943 if (i < startx) startx = i;
944 if (j < starty) starty = j;
945 if (i > endx) endx = i;
946 if (j > endy) endy = j;
955 if (startx < 0) startx = 0;
956 if (starty < 0) starty = 0;
957 if (endx > 512 - 1) endx = 512 - 1;
958 if (endy > 512 - 1) endy = 512 - 1;
959 if (endx < startx) endx = startx;
960 if (endy < starty) endy = starty;
962 startx /= realtexdetail;
963 starty /= realtexdetail;
964 endx /= realtexdetail;
965 endy /= realtexdetail;
967 int texdetailint = realtexdetail;
969 if (creature == rabbittype)
970 for (i = startx; i < endx; i++) {
971 for (j = starty; j < endy; j++) {
972 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) {
973 color = Random() % 85 + 170;
974 where = i * skeleton.skinsize * 3 + j * 3;
975 if (skeleton.skinText[where + 0] > color / 2)
976 skeleton.skinText[where + 0] = color / 2;
977 skeleton.skinText[where + 1] = 0;
978 skeleton.skinText[where + 2] = 0;
979 } 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) {
980 color = Random() % 85 + 170;
981 where = i * skeleton.skinsize * 3 + j * 3;
982 if (skeleton.skinText[where + 0] > color / 2)
983 skeleton.skinText[where + 0] = color / 2;
984 skeleton.skinText[where + 1] = 0;
985 skeleton.skinText[where + 2] = 0;
989 if (creature == wolftype)
990 for (i = startx; i < endx; i++) {
991 for (j = starty; j < endy; j++) {
992 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) {
993 color = Random() % 85 + 170;
994 where = i * skeleton.skinsize * 3 + j * 3;
995 if (skeleton.skinText[where + 0] > color / 2)
996 skeleton.skinText[where + 0] = color / 2;
997 skeleton.skinText[where + 1] = 0;
998 skeleton.skinText[where + 2] = 0;
999 } 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) {
1000 color = Random() % 85 + 170;
1001 where = i * skeleton.skinsize * 3 + j * 3;
1002 if (skeleton.skinText[where + 0] > color / 2)
1003 skeleton.skinText[where + 0] = color / 2;
1004 skeleton.skinText[where + 1] = 0;
1005 skeleton.skinText[where + 2] = 0;
1009 skeleton.drawmodel.textureptr.bind();
1012 bleedy = (1 + coordsy) * 512;
1013 bleedx = coordsx * 512;
1014 bleedy /= realtexdetail;
1015 bleedx /= realtexdetail;
1020 if (bleedx > skeleton.skinsize - 1)
1021 bleedx = skeleton.skinsize - 1;
1022 if (bleedy > skeleton.skinsize - 1)
1023 bleedy = skeleton.skinsize - 1;
1024 direction = abs(Random() % 2) * 2 - 1;
1029 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1030 deathbleeding += bleeding;
1031 bloodloss += bleeding * 3;
1033 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1034 if (abs(Random() % 2) == 0) {
1035 aitype = gethelptype;
1038 aitype = attacktypecutoff;
1049 * guessing this performs a reversal
1051 void Person::Reverse()
1053 if (!((victim->aitype == playercontrolled
1055 || staggerdelay <= 0)
1056 && victim->animTarget != jumpupanim
1057 && victim->animTarget != jumpdownanim
1058 && (tutoriallevel != 1 || cananger)
1062 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1063 && (victim->id != 0 || difficulty >= 2)
1064 && (creature != wolftype || victim->creature == wolftype))
1067 if (animTarget == sweepanim) {
1068 animTarget = sweepreversedanim;
1069 animCurrent = sweepreversedanim;
1070 victim->animCurrent = sweepreversalanim;
1071 victim->animTarget = sweepreversalanim;
1073 if (animTarget == spinkickanim) {
1074 animTarget = spinkickreversedanim;
1075 animCurrent = spinkickreversedanim;
1076 victim->animCurrent = spinkickreversalanim;
1077 victim->animTarget = spinkickreversalanim;
1079 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1080 if (animTarget == rabbittacklinganim) {
1083 victim->frameCurrent = 6;
1084 victim->frameTarget = 7;
1086 animTarget = upunchreversedanim;
1087 animCurrent = upunchreversedanim;
1088 victim->animCurrent = upunchreversalanim;
1089 victim->animTarget = upunchreversalanim;
1091 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1092 if (victim->weaponactive != -1) {
1093 victim->throwtogglekeydown = 1;
1094 XYZ tempVelocity = victim->velocity * .2;
1095 if (tempVelocity.x == 0)
1096 tempVelocity.x = .1;
1097 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1098 victim->num_weapons--;
1099 if (victim->num_weapons) {
1100 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1101 if (victim->weaponstuck == victim->num_weapons)
1102 victim->weaponstuck = 0;
1105 victim->weaponactive = -1;
1106 for (unsigned j = 0; j < Person::players.size(); j++) {
1107 Person::players[j]->wentforweapon = 0;
1111 animTarget = staffhitreversedanim;
1112 animCurrent = staffhitreversedanim;
1113 victim->animCurrent = staffhitreversalanim;
1114 victim->animTarget = staffhitreversalanim;
1116 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1117 if (victim->weaponactive != -1) {
1118 victim->throwtogglekeydown = 1;
1119 XYZ tempVelocity = victim->velocity * .2;
1120 if (tempVelocity.x == 0)
1121 tempVelocity.x = .1;
1122 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1123 victim->num_weapons--;
1124 if (victim->num_weapons) {
1125 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1126 if (victim->weaponstuck == victim->num_weapons)
1127 victim->weaponstuck = 0;
1130 victim->weaponactive = -1;
1131 for (unsigned j = 0; j < Person::players.size(); j++) {
1132 Person::players[j]->wentforweapon = 0;
1135 animTarget = staffspinhitreversedanim;
1136 animCurrent = staffspinhitreversedanim;
1137 victim->animCurrent = staffspinhitreversalanim;
1138 victim->animTarget = staffspinhitreversalanim;
1140 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1141 if (victim->weaponactive != -1) {
1142 victim->throwtogglekeydown = 1;
1143 XYZ tempVelocity = victim->velocity * .2;
1144 if (tempVelocity.x == 0)
1145 tempVelocity.x = .1;
1146 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1147 victim->num_weapons--;
1148 if (victim->num_weapons) {
1149 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1150 if (victim->weaponstuck == victim->num_weapons)
1151 victim->weaponstuck = 0;
1154 victim->weaponactive = -1;
1155 for (unsigned j = 0; j < Person::players.size(); j++) {
1156 Person::players[j]->wentforweapon = 0;
1159 animTarget = swordslashreversedanim;
1160 animCurrent = swordslashreversedanim;
1161 victim->animCurrent = swordslashreversalanim;
1162 victim->animTarget = swordslashreversalanim;
1164 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1165 if (victim->weaponactive != -1) {
1166 victim->throwtogglekeydown = 1;
1167 XYZ tempVelocity = victim->velocity * .2;
1168 if (tempVelocity.x == 0)
1169 tempVelocity.x = .1;
1170 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1171 victim->num_weapons--;
1172 if (victim->num_weapons) {
1173 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1174 if (victim->weaponstuck == victim->num_weapons)
1175 victim->weaponstuck = 0;
1178 victim->weaponactive = -1;
1179 for (unsigned j = 0; j < Person::players.size(); j++) {
1180 Person::players[j]->wentforweapon = 0;
1183 animTarget = knifeslashreversedanim;
1184 animCurrent = knifeslashreversedanim;
1185 victim->animCurrent = knifeslashreversalanim;
1186 victim->animTarget = knifeslashreversalanim;
1188 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1189 victim->targettilt2 = targettilt2;
1190 victim->frameCurrent = frameCurrent;
1191 victim->frameTarget = frameTarget;
1192 victim->target = target;
1193 victim->velocity = 0;
1194 victim->oldcoords = victim->coords;
1195 victim->coords = coords;
1196 victim->targetyaw = targetyaw;
1197 victim->yaw = targetyaw;
1198 victim->victim = this->shared_from_this();
1200 if (animTarget == winduppunchanim) {
1201 animTarget = winduppunchblockedanim;
1202 victim->animTarget = blockhighleftanim;
1203 victim->frameTarget = 1;
1204 victim->target = .5;
1205 victim->victim = this->shared_from_this();
1206 victim->targetyaw = targetyaw + 180;
1208 if (animTarget == wolfslapanim) {
1209 animTarget = winduppunchblockedanim;
1210 victim->animTarget = blockhighleftanim;
1211 victim->frameTarget = 1;
1212 victim->target = .5;
1213 victim->victim = this->shared_from_this();
1214 victim->targetyaw = targetyaw + 180;
1216 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1217 animTarget = swordslashparriedanim;
1218 parriedrecently = .4;
1219 victim->parriedrecently = 0;
1220 victim->animTarget = swordslashparryanim;
1221 victim->frameTarget = 1;
1222 victim->target = .5;
1223 victim->victim = this->shared_from_this();
1224 victim->targetyaw = targetyaw + 180;
1226 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1227 if (victim->weaponactive != -1) {
1228 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1229 if (weapons[victim->weaponids[0]].getType() == staff)
1230 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1231 if (weapons[weaponids[0]].getType() == staff)
1232 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1233 emit_sound_at(swordstaffsound, victim->coords);
1235 emit_sound_at(metalhitsound, victim->coords);
1239 victim->Puff(righthand);
1241 victim->frameTarget = 0;
1242 victim->animTarget = staggerbackhighanim;
1243 victim->targetyaw = targetyaw + 180;
1245 aim = DoRotation(facing, 0, 90, 0) * 21;
1247 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1248 victim->num_weapons--;
1249 if (victim->num_weapons) {
1250 victim->weaponids[0] = victim->weaponids[num_weapons];
1251 if (victim->weaponstuck == victim->num_weapons)
1252 victim->weaponstuck = 0;
1254 victim->weaponactive = -1;
1255 for (unsigned i = 0; i < Person::players.size(); i++) {
1256 Person::players[i]->wentforweapon = 0;
1260 if (abs(Random() % 20) == 0) {
1261 if (weaponactive != -1) {
1262 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1263 if (weapons[victim->weaponids[0]].getType() == staff)
1264 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1265 if (weapons[weaponids[0]].getType() == staff)
1266 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1268 emit_sound_at(swordstaffsound, coords);
1270 emit_sound_at(metalhitsound, coords);
1278 animTarget = staggerbackhighanim;
1279 targetyaw = targetyaw + 180;
1281 aim = DoRotation(facing, 0, 90, 0) * 21;
1283 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1286 weaponids[0] = weaponids[num_weapons];
1287 if (weaponstuck == num_weapons)
1291 for (unsigned i = 0; i < Person::players.size(); i++) {
1292 Person::players[i]->wentforweapon = 0;
1299 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1300 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1301 victim->animTarget = dodgebackanim;
1302 victim->frameTarget = 0;
1306 rotatetarget = coords - victim->coords;
1307 Normalise(&rotatetarget);
1308 victim->targetyaw = -asin(0 - rotatetarget.x);
1309 victim->targetyaw *= 360 / 6.28;
1310 if (rotatetarget.z < 0)
1311 victim->targetyaw = 180 - victim->targetyaw;
1313 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1315 victim->lastattack3 = victim->lastattack2;
1316 victim->lastattack2 = victim->lastattack;
1317 victim->lastattack = victim->animTarget;
1319 victim->animTarget = sweepanim;
1320 victim->frameTarget = 0;
1324 rotatetarget = coords - victim->coords;
1325 Normalise(&rotatetarget);
1326 victim->targetyaw = -asin(0 - rotatetarget.x);
1327 victim->targetyaw *= 360 / 6.28;
1328 if (rotatetarget.z < 0)
1329 victim->targetyaw = 180 - victim->targetyaw;
1331 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1333 victim->lastattack3 = victim->lastattack2;
1334 victim->lastattack2 = victim->lastattack;
1335 victim->lastattack = victim->animTarget;
1340 victim->velocity = 0;
1342 if (aitype != playercontrolled)
1344 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1346 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1348 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1351 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1358 void Person::DoDamage(float howmuch)
1360 // subtract health (temporary?)
1361 if (tutoriallevel != 1)
1362 damage += howmuch / power;
1365 damagedealt += howmuch / power;
1367 damagetaken += howmuch / power;
1370 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1373 if (tutoriallevel != 1)
1374 permanentdamage += howmuch / 2 / power;
1375 if (tutoriallevel != 1)
1376 superpermanentdamage += howmuch / 4 / power;
1378 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1380 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1384 camerashake += howmuch / 100;
1385 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1386 blackout = damage / damagetolerance;
1391 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1392 aitype = attacktypecutoff;
1393 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1394 if (abs(Random() % 2) == 0) {
1395 aitype = gethelptype;
1398 aitype = attacktypecutoff;
1402 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1405 for (int i = 0; i < skeleton.num_joints; i++) {
1406 if (skeleton.free) {
1407 flatvelocity2 = skeleton.joints[i].velocity;
1408 flatfacing2 = skeleton.joints[i].position * scale + coords;
1410 flatvelocity2 = velocity;
1411 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1413 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1414 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1415 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1416 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1417 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1418 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1421 emit_sound_at(splattersound, coords);
1426 if (!dead && creature == wolftype) {
1427 award_bonus(0, Wolfbonus);
1434 if (tutoriallevel != 1 || id == 0)
1435 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1436 int whichsound = -1;
1438 if (creature == wolftype) {
1439 int i = abs(Random() % 2);
1441 whichsound = snarlsound;
1443 whichsound = snarl2sound;
1444 envsound[numenvsounds] = coords;
1445 envsoundvol[numenvsounds] = 16;
1446 envsoundlife[numenvsounds] = .4;
1449 if (creature == rabbittype) {
1450 int i = abs(Random() % 2);
1452 whichsound = rabbitpainsound;
1453 if (i == 1 && damage > damagetolerance)
1454 whichsound = rabbitpain1sound;
1455 envsound[numenvsounds] = coords;
1456 envsoundvol[numenvsounds] = 16;
1457 envsoundlife[numenvsounds] = .4;
1461 if (whichsound != -1) {
1462 emit_sound_at(whichsound, coords);
1469 * calculate/animate head facing direction?
1471 void Person::DoHead()
1473 static XYZ rotatearound;
1475 static float lookspeed = 500;
1477 if (!freeze && !winfreeze) {
1480 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1481 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1483 while (targetheadyaw > 180)targetheadyaw -= 360;
1484 while (targetheadyaw < -180)targetheadyaw += 360;
1486 if (targetheadyaw > 160)
1487 targetheadpitch = targetheadpitch * -1;
1488 if (targetheadyaw < -160)
1489 targetheadpitch = targetheadpitch * -1;
1490 if (targetheadyaw > 160)
1491 targetheadyaw = targetheadyaw - 180;
1492 if (targetheadyaw < -160)
1493 targetheadyaw = targetheadyaw + 180;
1495 if (targetheadpitch > 120)
1496 targetheadpitch = 120;
1497 if (targetheadpitch < -120)
1498 targetheadpitch = -120;
1499 if (targetheadyaw > 120)
1500 targetheadyaw = 120;
1501 if (targetheadyaw < -120)
1502 targetheadyaw = -120;
1505 targetheadpitch = 0;
1507 if (targetheadyaw > 80)
1509 if (targetheadyaw < -80)
1510 targetheadyaw = -80;
1511 if (targetheadpitch > 50)
1512 targetheadpitch = 50;
1513 if (targetheadpitch < -50)
1514 targetheadpitch = -50;
1517 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1518 headyaw = targetheadyaw;
1519 else if (headyaw > targetheadyaw) {
1520 headyaw -= multiplier * lookspeed;
1521 } else if (headyaw < targetheadyaw) {
1522 headyaw += multiplier * lookspeed;
1525 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1526 headpitch = targetheadpitch;
1527 else if (headpitch > targetheadpitch) {
1528 headpitch -= multiplier * lookspeed / 2;
1529 } else if (headpitch < targetheadpitch) {
1530 headpitch += multiplier * lookspeed / 2;
1533 rotatearound = jointPos(neck);
1534 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1538 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1539 facing = DoRotation(facing, headpitch * .4, 0, 0);
1540 facing = DoRotation(facing, 0, headyaw * .4, 0);
1543 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1544 facing = DoRotation(facing, headpitch * .8, 0, 0);
1545 facing = DoRotation(facing, 0, headyaw * .8, 0);
1548 if (animTarget == walkanim) {
1549 facing = DoRotation(facing, headpitch * .6, 0, 0);
1550 facing = DoRotation(facing, 0, headyaw * .6, 0);
1553 skeleton.specialforward[0] = facing;
1554 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1555 for (int i = 0; i < skeleton.num_muscles; i++) {
1556 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1557 skeleton.FindRotationMuscle(i, animTarget);
1564 * ragdolls character?
1566 void Person::RagDoll(bool checkcollision)
1571 if (!skeleton.free) {
1574 if (id == 0 && isFlip())
1581 facing = DoRotation(facing, 0, yaw, 0);
1583 skeleton.freetime = 0;
1585 skeleton.longdead = 0;
1588 skeleton.broken = 0;
1589 skeleton.spinny = 1;
1591 skeleton.freefall = 1;
1593 if (!isnormal(velocity.x)) velocity.x = 0;
1594 if (!isnormal(velocity.y)) velocity.y = 0;
1595 if (!isnormal(velocity.z)) velocity.z = 0;
1596 if (!isnormal(yaw)) yaw = 0;
1597 if (!isnormal(coords.x)) coords = 0;
1598 if (!isnormal(tilt)) tilt = 0;
1599 if (!isnormal(tilt2)) tilt2 = 0;
1601 for (int i = 0; i < skeleton.num_joints; i++) {
1602 skeleton.joints[i].delay = 0;
1603 skeleton.joints[i].locked = 0;
1604 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1605 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1606 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1607 skeleton.joints[i].position.y += .1;
1608 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1609 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1612 for (int i = 0; i < skeleton.num_joints; i++) {
1613 skeleton.joints[i].velocity = 0;
1614 skeleton.joints[i].velchange = 0;
1616 skeleton.DoConstraints(&coords, &scale);
1617 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1618 skeleton.DoConstraints(&coords, &scale);
1619 skeleton.DoConstraints(&coords, &scale);
1620 skeleton.DoConstraints(&coords, &scale);
1621 skeleton.DoConstraints(&coords, &scale);
1624 speed = animation[animTarget].speed[frameTarget] * 2;
1625 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1626 speed = animation[animCurrent].speed[frameCurrent] * 2;
1629 speed = transspeed * 2;
1633 for (int i = 0; i < skeleton.num_joints; i++) {
1634 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1635 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);
1637 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1638 change.x = (float)(Random() % 100) / 100;
1639 change.y = (float)(Random() % 100) / 100;
1640 change.z = (float)(Random() % 100) / 100;
1641 skeleton.joints[i].velocity += change;
1642 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
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].velchange += change;
1648 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1651 if (checkcollision) {
1658 for (j = 0; j < skeleton.num_joints; j++) {
1659 average += skeleton.joints[j].position;
1663 coords += average * scale;
1664 for (j = 0; j < skeleton.num_joints; j++) {
1665 skeleton.joints[j].position -= average;
1668 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1669 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1670 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1671 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1672 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1675 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1676 coords.x = lowpoint.x;
1677 coords.z = lowpoint.z;
1686 for (int i = 0; i < skeleton.num_joints; i++) {
1687 velocity += skeleton.joints[i].velocity * scale;
1689 velocity /= skeleton.num_joints;
1692 if (Random() % 2 == 0) {
1693 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1694 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1695 weapons[weaponids[0]].velocity.x += .01;
1698 weaponids[0] = weaponids[num_weapons];
1699 if (weaponstuck == num_weapons)
1703 for (unsigned i = 0; i < Person::players.size(); i++) {
1704 Person::players[i]->wentforweapon = 0;
1709 animTarget = bounceidleanim;
1710 animCurrent = bounceidleanim;
1720 void Person::FootLand(int which, float opacity)
1722 static XYZ terrainlight;
1723 static XYZ footvel, footpoint;
1724 if (opacity >= 1 || skiddelay <= 0)
1728 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1730 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1731 //footpoint.y=coords.y;
1732 if (distsq(&footpoint, &viewer))
1733 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1734 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1735 footvel = velocity / 5;
1739 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1741 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1742 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1743 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1744 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1745 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1746 if (opacity >= 1 || detail == 2)
1748 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1749 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1750 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1751 footvel = velocity / 5;
1755 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1757 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1758 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1759 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1760 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1761 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1762 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1763 footvel = velocity / 5;
1767 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1769 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1770 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1771 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1772 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1773 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1774 if (opacity >= 1 || detail == 2)
1776 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1777 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1778 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1779 footvel = velocity / 5;
1783 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1785 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1786 //footpoint.y=coords.y;
1787 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1788 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1793 * make a puff effect at a body part (dust effect?)
1795 void Person::Puff(int whichlabel)
1797 static XYZ footvel, footpoint;
1800 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1801 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1805 * I think I added this in an attempt to clean up code
1807 void Person::setAnimation(int animation)
1809 animTarget = animation;
1818 void Person::DoAnimations()
1820 if (!skeleton.free) {
1821 static float oldtarget;
1823 if (isIdle() && animCurrent != getIdle())
1824 normalsupdatedelay = 0;
1826 if (animTarget == tempanim || animCurrent == tempanim) {
1827 animation[tempanim] = tempanimation;
1829 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1835 vel[0] = velocity.x;
1836 vel[1] = velocity.y;
1837 vel[2] = velocity.z;
1840 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1841 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1843 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1845 if (!crouchkeydown && velocity.y >= -15)
1848 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1853 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1855 if (normaldotproduct(targfacing, velocity) >= -.3)
1856 animTarget = flipanim;
1858 animTarget = backflipanim;
1859 crouchtogglekeydown = 1;
1867 if (animation[animTarget].attack != reversed)
1869 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1870 crouchtogglekeydown = 0;
1871 if (aitype == playercontrolled)
1874 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1877 crouchtogglekeydown = 1;
1881 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1883 normalsupdatedelay = 0;
1887 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1889 emit_sound_at(fireendsound, coords);
1890 pause_sound(stream_firesound);
1894 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1895 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1897 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1898 if (normaldotproduct(victim->facing, facing) > 0)
1899 victim->animTarget = rabbittackledbackanim;
1901 victim->animTarget = rabbittackledfrontanim;
1902 victim->frameTarget = 2;
1905 victim->targetyaw = yaw;
1906 if (victim->aitype == gethelptype)
1907 victim->DoDamage(victim->damagetolerance - victim->damage);
1908 //victim->DoDamage(30);
1909 if (creature == wolftype) {
1911 emit_sound_at(clawslicesound, victim->coords);
1913 victim->DoBloodBig(1 / victim->armorhead, 210);
1915 award_bonus(id, TackleBonus,
1916 victim->aitype == gethelptype ? 50 : 0);
1920 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1921 if (weapons[weaponids[0]].getType() == knife) {
1922 if (weaponactive == -1)
1924 else if (weaponactive == 0)
1927 if (weaponactive == -1) {
1928 emit_sound_at(knifesheathesound, coords);
1930 if (weaponactive != -1) {
1931 emit_sound_at(knifedrawsound, coords, 128);
1934 drawtogglekeydown = 1;
1937 if (tutoriallevel != 1 || id == 0)
1938 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1941 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1942 if (animation[animTarget].label[frameTarget] == 1)
1943 whichsound = footstepsound;
1945 whichsound = footstepsound2;
1946 if (animation[animTarget].label[frameTarget] == 1)
1948 if (animation[animTarget].label[frameTarget] == 2)
1950 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1956 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1957 if (animation[animTarget].label[frameTarget] == 1)
1958 whichsound = footstepsound3;
1960 whichsound = footstepsound4;
1964 if (animation[animTarget].label[frameTarget] == 1)
1965 whichsound = footstepsound3;
1967 whichsound = footstepsound4;
1969 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1970 if (animation[animTarget].attack != neutral) {
1971 unsigned r = abs(Random() % 3);
1973 whichsound = lowwhooshsound;
1975 whichsound = midwhooshsound;
1977 whichsound = highwhooshsound;
1979 if (animation[animTarget].attack == neutral)
1980 whichsound = movewhooshsound;
1981 } else if (animation[animTarget].label[frameTarget] == 4)
1982 whichsound = knifeswishsound;
1983 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1984 whichsound = landsound2;
1986 emit_sound_at(whichsound, coords, 256.);
1989 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1990 envsound[numenvsounds] = coords;
1991 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1992 envsoundvol[numenvsounds] = 15;
1994 envsoundvol[numenvsounds] = 6;
1995 envsoundlife[numenvsounds] = .4;
1999 if (animation[animTarget].label[frameTarget] == 3) {
2001 emit_sound_at(whichsound, coords, 128.);
2006 if (tutoriallevel != 1 || id == 0)
2007 if (speechdelay <= 0)
2008 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2009 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2010 int whichsound = -1;
2011 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2012 if (animation[animTarget].attack != neutral) {
2013 unsigned r = abs(Random() % 4);
2014 if (creature == rabbittype) {
2015 if (r == 0) whichsound = rabbitattacksound;
2016 if (r == 1) whichsound = rabbitattack2sound;
2017 if (r == 2) whichsound = rabbitattack3sound;
2018 if (r == 3) whichsound = rabbitattack4sound;
2020 if (creature == wolftype) {
2021 if (r == 0) whichsound = barksound;
2022 if (r == 1) whichsound = bark2sound;
2023 if (r == 2) whichsound = bark3sound;
2024 if (r == 3) whichsound = barkgrowlsound;
2030 if (whichsound != -1) {
2031 emit_sound_at(whichsound, coords);
2037 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2043 currentoffset = targetoffset;
2044 frameTarget = frameCurrent;
2045 animCurrent = animTarget;
2048 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2049 for (unsigned i = 0; i < weapons.size(); i++) {
2050 if (weapons[i].owner == -1)
2051 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2052 if (distsq(&coords, &weapons[i].position) >= 1) {
2053 if (weapons[i].getType() != staff) {
2054 emit_sound_at(knifedrawsound, coords, 128.);
2063 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2064 for (unsigned i = 0; i < weapons.size(); i++) {
2065 bool willwork = true;
2066 if (weapons[i].owner != -1)
2067 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2068 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2069 if (Person::players[weapons[i].owner]->num_weapons > 1)
2071 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2072 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2073 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2074 bool fleshstuck = false;
2075 if (weapons[i].owner != -1)
2076 if (victim->weaponstuck != -1) {
2077 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2082 emit_sound_at(fleshstabremovesound, coords, 128.);
2084 if (weapons[i].getType() != staff) {
2085 emit_sound_at(knifedrawsound, coords, 128.);
2088 if (weapons[i].owner != -1) {
2089 victim = Person::players[weapons[i].owner];
2090 if (victim->num_weapons == 1)
2091 victim->num_weapons = 0;
2093 victim->num_weapons = 1;
2095 //victim->weaponactive=-1;
2096 victim->skeleton.longdead = 0;
2097 victim->skeleton.free = 1;
2098 victim->skeleton.broken = 0;
2100 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2101 victim->skeleton.joints[j].velchange = 0;
2102 victim->skeleton.joints[j].locked = 0;
2108 Normalise(&relative);
2109 XYZ footvel, footpoint;
2111 footpoint = weapons[i].position;
2112 if (victim->weaponstuck != -1) {
2113 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2115 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2116 weapons[i].bloody = 2;
2117 weapons[i].blooddrip = 5;
2118 victim->weaponstuck = -1;
2121 if (victim->num_weapons > 0) {
2122 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2123 victim->weaponstuck = 0;
2124 if (victim->weaponids[0] == int(i))
2125 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2128 victim->jointVel(abdomen) += relative * 6;
2129 victim->jointVel(neck) += relative * 6;
2130 victim->jointVel(rightshoulder) += relative * 6;
2131 victim->jointVel(leftshoulder) += relative * 6;
2139 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2140 if (weaponactive == -1)
2142 else if (weaponactive == 0) {
2144 if (num_weapons == 2) {
2146 buffer = weaponids[0];
2147 weaponids[0] = weaponids[1];
2148 weaponids[1] = buffer;
2151 if (weaponactive == -1) {
2152 emit_sound_at(knifesheathesound, coords, 128.);
2154 if (weaponactive != -1) {
2155 emit_sound_at(knifedrawsound, coords, 128.);
2160 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2161 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2162 Normalise(&rotatetarget);
2163 targetyaw = -asin(0 - rotatetarget.x);
2164 targetyaw *= 360 / 6.28;
2165 if (rotatetarget.z < 0)
2166 targetyaw = 180 - targetyaw;
2168 if (animTarget == walljumprightkickanim)
2170 if (animTarget == walljumpleftkickanim)
2176 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2179 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2184 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2185 animTarget = rabbittackleanim;
2187 emit_sound_at(jumpsound, coords);
2195 targetloc = velocity;
2196 Normalise(&targetloc);
2197 targetloc += coords;
2198 for (unsigned i = 0; i < Person::players.size(); i++) {
2200 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2201 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2205 if (closestid != -1)
2206 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2208 victim = Person::players[closestid];
2209 coords = victim->coords;
2210 animCurrent = rabbittacklinganim;
2211 animTarget = rabbittacklinganim;
2215 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2216 rotatetarget = coords - victim->coords;
2217 Normalise(&rotatetarget);
2218 targetyaw = -asin(0 - rotatetarget.x);
2219 targetyaw *= 360 / 6.28;
2220 if (rotatetarget.z < 0)
2221 targetyaw = 180 - targetyaw;
2223 if (animTarget != rabbitrunninganim) {
2224 emit_sound_at(jumpsound, coords, 128.);
2230 float damagemult = 1 * power;
2231 if (creature == wolftype)
2232 damagemult = 2.5 * power;
2234 damagemult /= victim->damagetolerance / 200;
2236 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2237 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2238 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2242 if (Random() % 2 || creature == wolftype) {
2245 if (creature == wolftype)
2248 if (tutoriallevel != 1) {
2249 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2251 if (creature == wolftype) {
2252 emit_sound_at(clawslicesound, victim->coords, 128.);
2254 victim->DoBloodBig(2 / victim->armorhead, 175);
2258 relative = victim->coords - coords;
2260 Normalise(&relative);
2261 relative = DoRotation(relative, 0, -90, 0);
2262 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2263 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2265 victim->jointVel(head) += relative * damagemult * 200;
2268 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2274 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2275 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2279 if (Random() % 2 || creature == wolftype) {
2281 if (creature == wolftype)
2284 emit_sound_at(whooshhitsound, victim->coords);
2285 if (creature == wolftype) {
2286 emit_sound_at(clawslicesound, victim->coords, 128.);
2288 victim->DoBloodBig(2, 175);
2292 relative = victim->coords - coords;
2294 Normalise(&relative);
2296 Normalise(&relative);
2297 relative = DoRotation(relative, 0, 90, 0);
2298 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2299 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2301 victim->jointVel(head) += relative * damagemult * 100;
2304 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2308 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2309 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2315 if (tutoriallevel != 1) {
2316 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2318 if (creature == wolftype) {
2319 emit_sound_at(clawslicesound, victim->coords, 128.);
2321 victim->DoBloodBig(2 / victim->armorhead, 175);
2327 Normalise(&relative);
2328 relative = DoRotation(relative, 0, -90, 0);
2329 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2330 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2332 victim->jointVel(head) += relative * damagemult * 200;
2335 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2337 if (victim->damage > victim->damagetolerance)
2338 award_bonus(id, style);
2344 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2345 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2351 if (tutoriallevel != 1) {
2352 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2354 if (creature == wolftype) {
2355 emit_sound_at(clawslicesound, victim->coords, 128.);
2357 victim->DoBloodBig(2 / victim->armorhead, 175);
2363 Normalise(&relative);
2364 relative = DoRotation(relative, 0, 90, 0);
2365 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2366 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2368 victim->jointVel(head) += relative * damagemult * 200;
2371 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2373 if (victim->damage > victim->damagetolerance)
2374 award_bonus(id, style);
2380 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2381 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2389 emit_sound_at(whooshhitsound, victim->coords);
2392 relative = victim->coords - coords;
2394 Normalise(&relative);
2395 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2396 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2398 victim->jointVel(head) += relative * damagemult * 100;
2401 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2405 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2406 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2410 emit_sound_at(whooshhitsound, victim->coords, 128.);
2412 victim->skeleton.longdead = 0;
2413 victim->skeleton.free = 1;
2414 victim->skeleton.broken = 0;
2415 victim->skeleton.spinny = 1;
2417 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2418 victim->skeleton.joints[i].velchange = 0;
2419 victim->skeleton.joints[i].delay = 0;
2420 victim->skeleton.joints[i].locked = 0;
2421 //victim->skeleton.joints[i].velocity=0;
2427 Normalise(&relative);
2428 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2429 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2430 victim->skeleton.joints[i].position.y += relative.y * .3;
2431 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2432 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2434 victim->Puff(abdomen);
2435 victim->jointVel(abdomen).y = relative.y * 400;
2439 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2440 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2444 if (tutoriallevel != 1) {
2445 emit_sound_at(heavyimpactsound, coords, 128.);
2448 relative = victim->coords - coords;
2450 Normalise(&relative);
2451 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2452 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2454 victim->Puff(abdomen);
2455 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2459 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2460 victim->jointVel(abdomen) += relative * damagemult * 300;
2464 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2465 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2469 if (tutoriallevel != 1) {
2470 emit_sound_at(thudsound, coords);
2473 victim->skeleton.longdead = 0;
2474 victim->skeleton.free = 1;
2475 victim->skeleton.broken = 0;
2476 victim->skeleton.spinny = 1;
2478 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2479 victim->skeleton.joints[i].velchange = 0;
2480 //victim->skeleton.joints[i].delay=0;
2481 victim->skeleton.joints[i].locked = 0;
2484 relative = victim->coords - coords;
2485 Normalise(&relative);
2487 Normalise(&relative);
2488 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2489 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2494 victim->Puff(abdomen);
2495 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2496 victim->jointVel(abdomen) += relative * damagemult * 200;
2505 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2508 if (!victim->skeleton.free)
2512 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2513 emit_sound_at(knifesheathesound, coords, 128.);
2516 if (victim && hasvictim) {
2517 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2519 XYZ where, startpoint, endpoint, movepoint, colpoint;
2520 float rotationpoint;
2522 if (weapons[weaponids[weaponactive]].getType() == knife) {
2523 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2524 where -= victim->coords;
2525 if (!victim->skeleton.free)
2526 where = DoRotation(where, 0, -victim->yaw, 0);
2529 startpoint.y += 100;
2533 if (weapons[weaponids[weaponactive]].getType() == sword) {
2534 where = weapons[weaponids[weaponactive]].position;
2535 where -= victim->coords;
2536 if (!victim->skeleton.free)
2537 where = DoRotation(where, 0, -victim->yaw, 0);
2539 where = weapons[weaponids[weaponactive]].tippoint;
2540 where -= victim->coords;
2541 if (!victim->skeleton.free)
2542 where = DoRotation(where, 0, -victim->yaw, 0);
2545 if (weapons[weaponids[weaponactive]].getType() == staff) {
2546 where = weapons[weaponids[weaponactive]].position;
2547 where -= victim->coords;
2548 if (!victim->skeleton.free)
2549 where = DoRotation(where, 0, -victim->yaw, 0);
2551 where = weapons[weaponids[weaponactive]].tippoint;
2552 where -= victim->coords;
2553 if (!victim->skeleton.free)
2554 where = DoRotation(where, 0, -victim->yaw, 0);
2559 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2561 if (whichtri != -1) {
2562 if (victim->dead != 2) {
2563 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2565 award_bonus(id, FinishedBonus);
2568 weapons[weaponids[weaponactive]].bloody = 2;
2570 victim->skeleton.longdead = 0;
2571 victim->skeleton.free = 1;
2572 victim->skeleton.broken = 0;
2574 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2575 victim->skeleton.joints[i].velchange = 0;
2576 victim->skeleton.joints[i].locked = 0;
2577 //victim->skeleton.joints[i].velocity=0;
2579 emit_sound_at(fleshstabsound, coords, 128);
2582 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2583 weapons[weaponids[weaponactive]].blooddrip += 5;
2584 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2586 if (whichtri == -1) {
2588 emit_sound_at(knifesheathesound, coords, 128.);
2594 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2596 emit_sound_at(knifedrawsound, coords, 128);
2599 if (victim && hasvictim) {
2600 XYZ footvel, footpoint;
2602 emit_sound_at(fleshstabremovesound, coords, 128.);
2605 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2607 if (weapons[weaponids[weaponactive]].getType() == sword) {
2608 XYZ where, startpoint, endpoint, movepoint;
2609 float rotationpoint;
2612 where = weapons[weaponids[weaponactive]].position;
2613 where -= victim->coords;
2614 if (!victim->skeleton.free)
2615 where = DoRotation(where, 0, -victim->yaw, 0);
2617 where = weapons[weaponids[weaponactive]].tippoint;
2618 where -= victim->coords;
2619 if (!victim->skeleton.free)
2620 where = DoRotation(where, 0, -victim->yaw, 0);
2625 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2626 footpoint += victim->coords;
2628 if (whichtri == -1) {
2629 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2632 if (weapons[weaponids[weaponactive]].getType() == staff) {
2633 XYZ where, startpoint, endpoint, movepoint;
2634 float rotationpoint;
2637 where = weapons[weaponids[weaponactive]].position;
2638 where -= victim->coords;
2639 if (!victim->skeleton.free)
2640 where = DoRotation(where, 0, -victim->yaw, 0);
2642 where = weapons[weaponids[weaponactive]].tippoint;
2643 where -= victim->coords;
2644 if (!victim->skeleton.free)
2645 where = DoRotation(where, 0, -victim->yaw, 0);
2650 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2651 footpoint += victim->coords;
2653 if (whichtri == -1) {
2654 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2657 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2659 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2660 victim->skeleton.longdead = 0;
2661 victim->skeleton.free = 1;
2662 victim->skeleton.broken = 0;
2664 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2665 victim->skeleton.joints[i].velchange = 0;
2666 victim->skeleton.joints[i].locked = 0;
2667 //victim->skeleton.joints[i].velocity=0;
2673 Normalise(&relative);
2674 //victim->Puff(abdomen);
2676 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2678 if (victim->bloodloss < victim->damagetolerance) {
2679 victim->bloodloss += 1000;
2683 victim->jointVel(abdomen) += relative * damagemult * 20;
2687 if (!hasvictim && onterrain) {
2688 weapons[weaponids[weaponactive]].bloody = 0;
2689 weapons[weaponids[weaponactive]].blooddrip = 0;
2693 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2694 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2702 if (tutoriallevel != 1) {
2703 emit_sound_at(heavyimpactsound, victim->coords, 128);
2708 relative = victim->coords - coords;
2710 Normalise(&relative);
2711 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2712 victim->skeleton.joints[i].velocity = relative * 30;
2714 victim->jointVel(head) += relative * damagemult * 150;
2716 victim->frameTarget = 0;
2717 victim->animTarget = staggerbackhardanim;
2718 victim->targetyaw = targetyaw + 180;
2720 victim->stunned = 1;
2723 victim->Puff(abdomen);
2724 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2731 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2732 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2736 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2737 if (tutoriallevel != 1) {
2738 emit_sound_at(thudsound, victim->coords);
2740 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2741 if (tutoriallevel != 1) {
2742 emit_sound_at(whooshhitsound, victim->coords);
2745 if (tutoriallevel != 1) {
2746 emit_sound_at(heavyimpactsound, victim->coords);
2750 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2753 relative = victim->coords - coords;
2755 Normalise(&relative);
2757 Normalise(&relative);
2758 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2759 victim->skeleton.joints[i].velocity = relative * 5;
2761 victim->jointVel(abdomen) += relative * damagemult * 400;
2763 victim->frameTarget = 0;
2764 victim->animTarget = staggerbackhardanim;
2765 victim->targetyaw = targetyaw + 180;
2767 victim->stunned = 1;
2769 victim->Puff(abdomen);
2770 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2776 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2777 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2778 if (victim->id == 0)
2780 emit_sound_at(landsound2, victim->coords);
2786 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2787 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2788 if (victim->id == 0)
2791 if (weaponactive != -1) {
2792 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2793 if (weapons[victim->weaponids[0]].getType() == staff)
2794 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2795 if (weapons[weaponids[0]].getType() == staff)
2796 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2798 emit_sound_at(swordstaffsound, victim->coords);
2800 emit_sound_at(metalhitsound, victim->coords);
2808 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2809 if (weaponactive != -1) {
2812 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);
2814 weapons[weaponids[0]].thrown(aim * 50);
2817 weaponids[0] = weaponids[num_weapons];
2823 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2825 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2827 if (tutoriallevel != 1)
2828 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2830 award_bonus(id, Slicebonus);
2831 if (tutoriallevel != 1) {
2832 emit_sound_at(knifeslicesound, victim->coords);
2834 //victim->jointVel(abdomen)+=relative*damagemult*200;
2835 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2836 if (victim->id != 0 || difficulty == 2) {
2837 victim->frameTarget = 0;
2838 victim->animTarget = staggerbackhardanim;
2839 victim->targetyaw = targetyaw + 180;
2843 victim->lowreversaldelay = 0;
2844 victim->highreversaldelay = 0;
2845 if (aitype != playercontrolled)
2846 weaponmissdelay = .6;
2848 if (tutoriallevel != 1)
2849 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2850 weapons[weaponids[weaponactive]].bloody = 1;
2851 if (tutoriallevel != 1)
2852 weapons[weaponids[weaponactive]].blooddrip += 3;
2854 XYZ footvel, footpoint;
2856 if (skeleton.free) {
2857 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2859 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2861 if (tutoriallevel != 1) {
2863 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2864 footvel = DoRotation(facing, 0, 90, 0) * .8;
2866 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2867 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2868 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2869 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2871 if (tutoriallevel == 1) {
2872 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2874 victim->DoDamage(damagemult * 0);
2877 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2878 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2879 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2880 award_bonus(id, Slashbonus);
2882 if (tutoriallevel != 1) {
2883 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2884 victim->DoBloodBig(2 / victim->armorhigh, 190);
2886 victim->DoBloodBig(2 / victim->armorhigh, 185);
2887 victim->deathbleeding = 1;
2888 emit_sound_at(swordslicesound, victim->coords);
2890 //victim->jointVel(abdomen)+=relative*damagemult*200;
2891 if (tutoriallevel != 1) {
2892 victim->frameTarget = 0;
2893 victim->animTarget = staggerbackhardanim;
2894 victim->targetyaw = targetyaw + 180;
2898 if (tutoriallevel != 1) {
2899 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2900 weapons[weaponids[weaponactive]].bloody = 1;
2901 weapons[weaponids[weaponactive]].blooddrip += 3;
2903 float bloodlossamount;
2904 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2905 victim->bloodloss += bloodlossamount / victim->armorhigh;
2906 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2907 victim->DoDamage(damagemult * 0);
2909 XYZ footvel, footpoint;
2911 if (skeleton.free) {
2912 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2914 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2917 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2918 footvel = DoRotation(facing, 0, 90, 0) * .8;
2920 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2921 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2922 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2923 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2926 if (victim->weaponactive != -1) {
2927 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2928 if (weapons[victim->weaponids[0]].getType() == staff)
2929 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2930 if (weapons[weaponids[0]].getType() == staff)
2931 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2933 emit_sound_at(swordstaffsound, victim->coords);
2935 emit_sound_at(metalhitsound, victim->coords);
2941 victim->Puff(righthand);
2943 victim->frameTarget = 0;
2944 victim->animTarget = staggerbackhighanim;
2945 victim->targetyaw = targetyaw + 180;
2947 aim = DoRotation(facing, 0, 90, 0) * 21;
2949 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2950 victim->num_weapons--;
2951 if (victim->num_weapons) {
2952 victim->weaponids[0] = victim->weaponids[num_weapons];
2953 if (victim->weaponstuck == victim->num_weapons)
2954 victim->weaponstuck = 0;
2956 victim->weaponactive = -1;
2957 for (unsigned i = 0; i < Person::players.size(); i++) {
2958 Person::players[i]->wentforweapon = 0;
2965 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2966 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2967 if (tutoriallevel != 1) {
2968 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2972 if (Random() % 2 || creature == wolftype) {
2975 emit_sound_at(staffheadsound, victim->coords);
2979 relative = victim->coords - coords;
2981 Normalise(&relative);
2982 relative = DoRotation(relative, 0, 90, 0);
2984 Normalise(&relative);
2985 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2986 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2988 victim->jointVel(head) += relative * damagemult * 230;
2989 victim->jointVel(neck) += relative * damagemult * 230;
2992 if (tutoriallevel != 1) {
2993 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2995 award_bonus(id, solidhit, 30);
3000 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3001 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3002 if (tutoriallevel != 1) {
3003 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3007 if (Random() % 2 || creature == wolftype) {
3010 emit_sound_at(staffheadsound, victim->coords);
3014 relative = victim->coords - coords;
3016 Normalise(&relative);
3017 relative = DoRotation(relative, 0, -90, 0);
3018 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3019 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3021 victim->jointVel(head) += relative * damagemult * 220;
3022 victim->jointVel(neck) += relative * damagemult * 220;
3025 if (tutoriallevel != 1) {
3026 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3028 award_bonus(id, solidhit, 60);
3033 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3034 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3036 if (tutoriallevel != 1) {
3038 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3041 if (Random() % 2 || creature == wolftype) {
3044 emit_sound_at(staffbodysound, victim->coords);
3046 victim->skeleton.longdead = 0;
3047 victim->skeleton.free = 1;
3048 victim->skeleton.broken = 0;
3050 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3051 victim->skeleton.joints[i].velchange = 0;
3052 victim->skeleton.joints[i].locked = 0;
3053 //victim->skeleton.joints[i].velocity=0;
3059 /*relative=victim->coords-coords;
3061 Normalise(&relative);
3062 relative=DoRotation(relative,0,90,0);*/
3064 Normalise(&relative);
3065 if (!victim->dead) {
3066 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3067 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3070 victim->jointVel(abdomen) += relative * damagemult * 40;
3073 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3074 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3077 //victim->jointVel(abdomen)+=relative*damagemult*20;
3079 victim->Puff(abdomen);
3080 if (tutoriallevel != 1) {
3081 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3083 if (!victim->dead) {
3084 award_bonus(id, solidhit, 40);
3090 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3091 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3096 relative = victim->coords - coords;
3098 Normalise(&relative);
3102 if (animation[victim->animTarget].height == lowheight) {
3108 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3109 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3111 victim->jointVel(head) += relative * damagemult * 200;
3112 if (tutoriallevel != 1) {
3113 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3116 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3117 if (victim->howactive == typesleeping)
3118 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3119 if (creature == wolftype) {
3120 emit_sound_at(clawslicesound, victim->coords, 128.);
3122 victim->DoBloodBig(2 / victim->armorhead, 175);
3125 if (victim->damage >= victim->damagetolerance)
3127 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3128 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3130 victim->jointVel(abdomen) += relative * damagemult * 200;
3131 victim->frameTarget = 0;
3132 victim->animTarget = staggerbackhighanim;
3133 victim->targetyaw = targetyaw + 180;
3135 if (tutoriallevel != 1) {
3136 emit_sound_at(landsound2, victim->coords, 128.);
3138 victim->Puff(abdomen);
3139 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3140 if (creature == wolftype) {
3141 emit_sound_at(clawslicesound, victim->coords, 128.);
3143 victim->DoBloodBig(2 / victim->armorhigh, 170);
3150 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3151 if ((victim->animTarget != jumpupanim) &&
3152 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3153 (victim != this->shared_from_this())) {
3157 if (tutoriallevel != 1) {
3158 emit_sound_at(landsound2, victim->coords, 128.);
3161 relative = victim->coords - coords;
3163 Normalise(&relative);
3165 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3168 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3169 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3171 relative = DoRotation(relative, 0, -90, 0);
3173 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3174 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)
3175 victim->skeleton.joints[i].velocity = relative * 80;
3177 victim->Puff(rightankle);
3178 victim->Puff(leftankle);
3179 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3181 if (victim->damage >= victim->damagetolerance)
3183 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3184 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3186 relative = DoRotation(relative, 0, -90, 0);
3187 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3188 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)
3189 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3191 victim->jointVel(abdomen) += relative * damagemult * 200;
3192 victim->frameTarget = 0;
3193 victim->animTarget = staggerbackhighanim;
3194 victim->targetyaw = targetyaw + 180;
3196 if (tutoriallevel != 1) {
3197 emit_sound_at(landsound2, victim->coords, 128.);
3199 victim->Puff(abdomen);
3200 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3208 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3209 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3217 if (tutoriallevel != 1) {
3218 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3220 if (creature == wolftype) {
3221 emit_sound_at(clawslicesound, victim->coords, 128);
3223 victim->DoBloodBig(2 / victim->armorhigh, 170);
3227 relative = victim->coords - oldcoords;
3229 Normalise(&relative);
3230 //relative=DoRotation(relative,0,-90,0);
3231 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3232 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3234 victim->jointVel(abdomen) += relative * damagemult * 200;
3236 victim->Puff(abdomen);
3237 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3239 award_bonus(id, Reversal);
3242 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3243 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3244 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3245 takeWeapon(victim->weaponids[victim->weaponactive]);
3246 victim->num_weapons--;
3247 if (victim->num_weapons > 0) {
3248 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3250 victim->weaponactive = -1;
3255 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3263 emit_sound_at(whooshhitsound, victim->coords, 128.);
3266 relative = victim->coords - oldcoords;
3268 Normalise(&relative);
3269 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3270 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3272 victim->jointVel(abdomen) += relative * damagemult * 200;
3274 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3277 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3286 award_bonus(id, staffreversebonus);
3288 if (tutoriallevel != 1) {
3289 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3292 award_bonus(id, staffreversebonus); // Huh, again?
3295 relative = victim->coords - oldcoords;
3297 Normalise(&relative);
3298 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3299 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3301 victim->jointVel(abdomen) += relative * damagemult * 200;
3303 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3306 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3312 Normalise(&relative);
3314 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3315 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3317 victim->jointVel(lefthand) *= .1;
3318 victim->jointVel(leftwrist) *= .2;
3319 victim->jointVel(leftelbow) *= .5;
3320 victim->jointVel(leftshoulder) *= .7;
3321 victim->jointVel(righthand) *= .1;
3322 victim->jointVel(rightwrist) *= .2;
3323 victim->jointVel(rightelbow) *= .5;
3324 victim->jointVel(rightshoulder) *= .7;
3326 victim->Puff(abdomen);
3327 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3329 award_bonus(id, Reversal);
3333 if (weaponactive != -1 || creature == wolftype)
3335 if (creature == rabbittype && weaponactive != -1)
3336 if (weapons[weaponids[0]].getType() == staff)
3339 if (weaponactive != -1) {
3340 victim->DoBloodBig(2 / victim->armorhigh, 225);
3341 emit_sound_at(knifeslicesound, victim->coords);
3342 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3343 weapons[weaponids[weaponactive]].bloody = 1;
3344 weapons[weaponids[weaponactive]].blooddrip += 3;
3346 if (weaponactive == -1 && creature == wolftype) {
3348 emit_sound_at(clawslicesound, victim->coords, 128.);
3350 victim->DoBloodBig(2 / victim->armorhigh, 175);
3357 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3363 Normalise(&relative);
3365 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3366 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3368 victim->jointVel(lefthand) *= .1 - 1;
3369 victim->jointVel(leftwrist) *= .2 - 1;
3370 victim->jointVel(leftelbow) *= .5 - 1;
3371 victim->jointVel(leftshoulder) *= .7 - 1;
3372 victim->jointVel(righthand) *= .1 - 1;
3373 victim->jointVel(rightwrist) *= .2 - 1;
3374 victim->jointVel(rightelbow) *= .5 - 1;
3375 victim->jointVel(rightshoulder) *= .7 - 1;
3377 award_bonus(id, swordreversebonus);
3380 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3388 if (tutoriallevel != 1) {
3389 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3393 relative = victim->coords - oldcoords;
3395 Normalise(&relative);
3396 relative = DoRotation(relative, 0, -90, 0);
3397 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3398 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3400 victim->jointVel(abdomen) += relative * damagemult * 200;
3401 victim->Puff(abdomen);
3402 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3404 award_bonus(id, Reversal);
3407 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3410 victim->skeleton.spinny = 0;
3412 relative = facing * -1;
3414 Normalise(&relative);
3415 if (victim->id == 0)
3417 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3418 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3420 victim->damage = victim->damagetolerance;
3421 victim->permanentdamage = victim->damagetolerance - 1;
3424 if (weaponactive != -1 || creature == wolftype)
3426 if (creature == rabbittype && weaponactive != -1)
3427 if (weapons[weaponids[0]].getType() == staff)
3430 if (weaponactive != -1) {
3431 victim->DoBloodBig(200, 225);
3432 emit_sound_at(knifeslicesound, victim->coords);
3434 weapons[weaponids[weaponactive]].bloody = 2;
3435 weapons[weaponids[weaponactive]].blooddrip += 5;
3438 if (creature == wolftype && weaponactive == -1) {
3439 emit_sound_at(clawslicesound, victim->coords, 128.);
3441 victim->DoBloodBig(2, 175);
3444 award_bonus(id, spinecrusher);
3447 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3448 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3450 if (animTarget == knifefollowanim)
3451 victim->DoBloodBig(200, 210);
3452 if (animTarget == knifesneakattackanim) {
3453 XYZ footvel, footpoint;
3455 footpoint = weapons[weaponids[0]].tippoint;
3457 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3458 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3459 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3460 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3461 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3462 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3463 victim->DoBloodBig(200, 195);
3464 award_bonus(id, tracheotomy);
3466 if (animTarget == knifefollowanim) {
3467 award_bonus(id, Stabbonus);
3468 XYZ footvel, footpoint;
3470 footpoint = weapons[weaponids[0]].tippoint;
3472 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3473 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3474 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3475 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3476 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3477 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3480 victim->bloodloss += 10000;
3481 victim->velocity = 0;
3482 emit_sound_at(fleshstabsound, victim->coords);
3484 weapons[weaponids[weaponactive]].bloody = 2;
3485 weapons[weaponids[weaponactive]].blooddrip += 5;
3489 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3491 victim->velocity = 0;
3492 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3493 victim->skeleton.joints[i].velocity = 0;
3495 if (animTarget == knifefollowanim) {
3497 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3498 victim->skeleton.joints[i].velocity = 0;
3501 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3502 emit_sound_at(fleshstabremovesound, victim->coords);
3504 weapons[weaponids[weaponactive]].bloody = 2;
3505 weapons[weaponids[weaponactive]].blooddrip += 5;
3507 XYZ footvel, footpoint;
3509 footpoint = weapons[weaponids[0]].tippoint;
3511 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3512 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3513 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3514 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3515 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3516 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3520 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3521 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3522 award_bonus(id, backstab);
3526 XYZ footvel, footpoint;
3528 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3530 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3531 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3532 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3533 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3534 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3535 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3536 victim->DoBloodBig(200, 180);
3537 victim->DoBloodBig(200, 215);
3538 victim->bloodloss += 10000;
3539 victim->velocity = 0;
3540 emit_sound_at(fleshstabsound, victim->coords);
3542 weapons[weaponids[weaponactive]].bloody = 2;
3543 weapons[weaponids[weaponactive]].blooddrip += 5;
3547 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3549 victim->velocity = 0;
3550 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3551 victim->skeleton.joints[i].velocity = 0;
3553 if (weaponactive != -1) {
3554 emit_sound_at(fleshstabremovesound, victim->coords);
3556 weapons[weaponids[weaponactive]].bloody = 2;
3557 weapons[weaponids[weaponactive]].blooddrip += 5;
3559 XYZ footvel, footpoint;
3561 footpoint = weapons[weaponids[0]].tippoint;
3563 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3564 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3565 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3566 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3567 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3568 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3572 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3580 if (weaponactive == -1) {
3581 if (tutoriallevel != 1) {
3582 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3587 if (weaponactive != -1 || creature == wolftype)
3589 if (creature == rabbittype && weaponactive != -1)
3590 if (weapons[weaponids[0]].getType() == staff)
3593 if (weaponactive != -1) {
3594 victim->DoBloodBig(2 / victim->armorhead, 225);
3595 emit_sound_at(knifeslicesound, victim->coords);
3596 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3597 weapons[weaponids[weaponactive]].bloody = 1;
3598 weapons[weaponids[weaponactive]].blooddrip += 3;
3600 if (weaponactive == -1 && creature == wolftype) {
3601 emit_sound_at(clawslicesound, victim->coords, 128.);
3603 victim->DoBloodBig(2 / victim->armorhead, 175);
3607 award_bonus(id, Reversal);
3612 relative = facing * -1;
3614 Normalise(&relative);
3615 relative = DoRotation(relative, 0, 90, 0);
3617 Normalise(&relative);
3618 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3619 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3621 victim->jointVel(head) += relative * damagemult * 200;
3622 if (victim->damage < victim->damagetolerance - 100)
3623 victim->velocity = relative * 200;
3624 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3625 victim->velocity = 0;
3628 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3632 relative = facing * -1;
3634 Normalise(&relative);
3635 relative = DoRotation(relative, 0, 90, 0);
3637 Normalise(&relative);
3638 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3639 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3641 victim->jointVel(head) += relative * damagemult * 200;
3644 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3645 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3646 award_bonus(id, reverseko);
3652 if (frameTarget > animation[animCurrent].numframes - 1) {
3655 animTarget = getIdle();
3659 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3660 animTarget = rollanim;
3662 emit_sound_at(movewhooshsound, coords, 128.);
3664 if (animCurrent == staggerbackhighanim) {
3665 animTarget = getIdle();
3667 if (animCurrent == staggerbackhardanim) {
3668 animTarget = getIdle();
3670 if (animCurrent == removeknifeanim) {
3671 animTarget = getIdle();
3673 if (animCurrent == crouchremoveknifeanim) {
3674 animTarget = getCrouch();
3676 if (animCurrent == backhandspringanim) {
3677 animTarget = getIdle();
3679 if (animCurrent == dodgebackanim) {
3680 animTarget = getIdle();
3682 if (animCurrent == drawleftanim) {
3683 animTarget = getIdle();
3685 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3686 animTarget = getIdle();
3687 if (animCurrent == crouchdrawrightanim) {
3688 animTarget = getCrouch();
3690 if (weaponactive == -1)
3692 else if (weaponactive == 0) {
3694 if (num_weapons == 2) {
3696 buffer = weaponids[0];
3697 weaponids[0] = weaponids[1];
3698 weaponids[1] = buffer;
3702 if (weaponactive == -1) {
3703 emit_sound_at(knifesheathesound, coords, 128.);
3705 if (weaponactive != -1) {
3706 emit_sound_at(knifedrawsound, coords, 128.);
3709 if (animCurrent == rollanim) {
3710 animTarget = getCrouch();
3715 if (animTarget == walljumprightkickanim) {
3718 if (animTarget == walljumpleftkickanim) {
3721 animTarget = jumpdownanim;
3723 if (animCurrent == climbanim) {
3724 animTarget = getCrouch();
3726 coords += facing * .1;
3727 if (!isnormal(coords.x))
3738 if (animTarget == rabbitkickreversalanim) {
3739 animTarget = getCrouch();
3742 if (animTarget == jumpreversalanim) {
3743 animTarget = getCrouch();
3746 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3747 if (attackkeydown && animTarget != walljumpfrontanim) {
3749 float closestdist = -1;
3751 if (Person::players.size() > 1)
3752 for (unsigned i = 0; i < Person::players.size(); i++) {
3753 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3754 distance = distsq(&Person::players[i]->coords, &coords);
3755 if (closestdist == -1 || distance < closestdist) {
3756 closestdist = distance;
3761 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3762 victim = Person::players[closest];
3763 animTarget = walljumprightkickanim;
3765 XYZ rotatetarget = victim->coords - coords;
3766 Normalise(&rotatetarget);
3767 yaw = -asin(0 - rotatetarget.x);
3769 if (rotatetarget.z < 0)
3771 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3772 velocity = (victim->coords - coords) * 4;
3777 if (animTarget == walljumpbackanim) {
3778 animTarget = backflipanim;
3780 velocity = facing * -8;
3783 resume_stream(whooshsound);
3785 if (animTarget == walljumprightanim) {
3786 animTarget = rightflipanim;
3790 velocity = DoRotation(facing, 0, 30, 0) * -8;
3793 if (animTarget == walljumpfrontanim) {
3794 animTarget = frontflipanim;
3798 velocity = facing * 8;
3802 resume_stream(whooshsound);
3804 if (animTarget == walljumpleftanim) {
3805 if (attackkeydown) {
3807 float closestdist = -1;
3809 if (Person::players.size() > 1)
3810 for (unsigned i = 0; i < Person::players.size(); i++) {
3811 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3812 distance = distsq(&Person::players[i]->coords, &coords);
3813 if (closestdist == -1 || distance < closestdist) {
3814 closestdist = distance;
3819 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3820 victim = Person::players[closest];
3821 animTarget = walljumpleftkickanim;
3823 XYZ rotatetarget = victim->coords - coords;
3824 Normalise(&rotatetarget);
3825 yaw = -asin(0 - rotatetarget.x);
3827 if (rotatetarget.z < 0)
3829 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3830 velocity = (victim->coords - coords) * 4;
3835 if (animTarget != walljumpleftkickanim) {
3836 animTarget = leftflipanim;
3840 velocity = DoRotation(facing, 0, -30, 0) * -8;
3844 resume_stream(whooshsound);
3846 if (animTarget == sneakattackanim) {
3847 animCurrent = getCrouch();
3848 animTarget = getCrouch();
3855 transspeed = 1000000;
3856 targetheadyaw += 180;
3857 coords -= facing * .7;
3859 coords.y = terrain.getHeight(coords.x, coords.z);
3863 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3864 animTarget = getIdle();
3867 coords.y = terrain.getHeight(coords.x, coords.z);
3871 if (animCurrent == knifefollowanim) {
3872 animTarget = getIdle();
3875 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3876 float ycoords = oldcoords.y;
3877 animTarget = getStop();
3882 transspeed = 1000000;
3883 targetheadyaw += 180;
3884 if (!isnormal(coords.x))
3886 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3887 oldcoords = coords + facing * .5;
3888 else if (animCurrent == sweepreversalanim)
3889 oldcoords = coords + facing * 1.1;
3890 else if (animCurrent == upunchreversalanim) {
3891 oldcoords = coords + facing * 1.5;
3894 targetheadyaw += 180;
3897 } else if (animCurrent == knifeslashreversalanim) {
3898 oldcoords = coords + facing * .5;
3901 targetheadyaw += 90;
3904 } else if (animCurrent == staffspinhitreversalanim) {
3907 targetheadyaw += 180;
3912 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3914 oldcoords.y = ycoords;
3915 currentoffset = coords - oldcoords;
3921 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3926 if (animation[animTarget].attack == reversed) {
3928 if (animTarget == sweepreversedanim)
3930 animTarget = backhandspringanim;
3932 emit_sound_at(landsound, coords, 128);
3934 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3935 animTarget = rollanim;
3938 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3939 coords.y = oldcoords.y;
3941 if (animCurrent == knifeslashreversedanim) {
3942 animTarget = rollanim;
3947 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3948 coords.y = oldcoords.y;
3952 animTarget = jumpdownanim;
3955 animTarget = getIdle();
3957 animTarget = getIdle();
3958 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3959 animTarget = getIdle();
3961 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3962 coords.y = oldcoords.y;
3963 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3964 targetoffset.y = coords.y;
3966 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3967 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3968 currentoffset.y -= (coords.y - targetoffset.y);
3969 coords.y = targetoffset.y;
3971 normalsupdatedelay = 0;
3973 if (animCurrent == upunchanim) {
3974 animTarget = getStop();
3975 normalsupdatedelay = 0;
3978 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3982 if (num_weapons > 0)
3983 if (weapons[0].getType() == staff)
3989 rabbitkickragdoll = 1;
3991 if (animCurrent == rabbitkickreversedanim) {
3997 skeleton.spinny = 0;
3998 SolidHitBonus(!id); // FIXME: tricky id
4002 animTarget = rollanim;
4005 pause_sound(whooshsound);
4009 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4013 skeleton.spinny = 0;
4015 if (animCurrent == jumpreversedanim) {
4021 skeleton.spinny = 0;
4022 SolidHitBonus(!id); // FIXME: tricky id
4026 animTarget = rollanim;
4027 coords += facing * 2;
4029 pause_sound(whooshsound);
4034 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) {
4035 animTarget = getupfromfrontanim;
4037 } else if (animation[animCurrent].attack == normalattack) {
4038 animTarget = getIdle();
4041 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4042 animTarget = blockhighleftstrikeanim;
4044 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4045 animTarget = getIdle();
4048 if (animCurrent == spinkickanim && victim->skeleton.free) {
4049 if (creature == rabbittype)
4050 animTarget = fightidleanim;
4055 if (isIdle() && !wasIdle())
4056 normalsupdatedelay = 0;
4058 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4059 animTarget = jumpdownanim;
4062 if (!skeleton.free) {
4064 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4065 if (!isRun() || !wasRun()) {
4066 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4067 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4068 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4069 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4071 if (isRun() && wasRun()) {
4073 tempspeed = velspeed;
4074 if (tempspeed < 10 * speedmult)
4075 tempspeed = 10 * speedmult;
4076 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4078 } else if (transspeed)
4079 target += multiplier * transspeed * speed * 2;
4081 if (!isRun() || !wasRun()) {
4082 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4083 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4084 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4085 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4089 if (animCurrent != animTarget)
4090 target = (target + oldtarget) / 2;
4093 frameCurrent = frameTarget;
4097 rot = targetrot * target;
4098 yaw += rot - oldrot;
4104 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4106 for (int i = 0; i < skeleton.num_joints; i++) {
4107 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4110 skeleton.FindForwards();
4112 for (int i = 0; i < skeleton.num_muscles; i++) {
4113 if (skeleton.muscles[i].visible) {
4114 skeleton.FindRotationMuscle(i, animTarget);
4117 for (int i = 0; i < skeleton.num_muscles; i++) {
4118 if (skeleton.muscles[i].visible) {
4119 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4120 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4121 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4122 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4123 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4124 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4129 for (int i = 0; i < skeleton.num_joints; i++) {
4130 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4133 skeleton.FindForwards();
4135 for (int i = 0; i < skeleton.num_muscles; i++) {
4136 if (skeleton.muscles[i].visible) {
4137 skeleton.FindRotationMuscle(i, animTarget);
4140 for (int i = 0; i < skeleton.num_muscles; i++) {
4141 if (skeleton.muscles[i].visible) {
4142 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4143 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4144 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4145 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4146 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4147 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4148 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4149 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4150 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4151 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4152 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4153 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4157 if (frameCurrent >= animation[animCurrent].numframes)
4158 frameCurrent = animation[animCurrent].numframes - 1;
4160 oldanimCurrent = animCurrent;
4161 oldanimTarget = animTarget;
4162 oldframeTarget = frameTarget;
4163 oldframeCurrent = frameCurrent;
4165 for (int i = 0; i < skeleton.num_joints; i++) {
4166 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4167 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4169 offset = currentoffset * (1 - target) + targetoffset * target;
4170 for (int i = 0; i < skeleton.num_muscles; i++) {
4171 if (skeleton.muscles[i].visible) {
4172 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4173 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4174 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4179 if (isLanding() && landhard) {
4182 animTarget = getLandhard();
4195 void Person::DoStuff()
4197 static XYZ terrainnormal;
4198 static XYZ flatfacing;
4199 static XYZ flatvelocity;
4200 static float flatvelspeed;
4204 static int bloodsize;
4205 static int startx, starty, endx, endy;
4206 static GLubyte color;
4207 static XYZ bloodvel;
4209 onfiredelay -= multiplier;
4210 if (onfiredelay < 0 && onfire) {
4211 if (Random() % 2 == 0) {
4217 crouchkeydowntime += multiplier;
4219 crouchkeydowntime = 0;
4220 jumpkeydowntime += multiplier;
4221 if (!jumpkeydown && skeleton.free)
4222 jumpkeydowntime = 0;
4224 if (hostile || damage > 0 || bloodloss > 0)
4227 if (isIdle() || isRun())
4230 if (num_weapons == 1 && weaponactive != -1)
4234 blooddimamount -= multiplier * .3;
4235 speechdelay -= multiplier;
4236 texupdatedelay -= multiplier;
4237 interestdelay -= multiplier;
4238 flamedelay -= multiplier;
4239 parriedrecently -= multiplier;
4241 victim = this->shared_from_this();
4246 speed = 1.1 * speedmult;
4248 speed = 1.0 * speedmult;
4250 rabbitkickragdoll = 0;
4254 if (id != 0 && (creature == rabbittype || difficulty != 2))
4256 if (id != 0 && creature == wolftype && difficulty == 2) {
4258 if (aitype != passivetype) {
4260 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) {
4266 if (animTarget == wolfrunninganim && !superruntoggle) {
4267 animTarget = getRun();
4271 if (weaponactive == -1 && num_weapons > 0) {
4272 if (weapons[weaponids[0]].getType() == staff) {
4278 burnt += multiplier;
4282 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4284 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4290 vel[0] = velocity.x;
4291 vel[1] = velocity.y;
4292 vel[2] = velocity.z;
4295 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4296 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4300 while (flamedelay < 0 && onfire) {
4302 howmany = abs(Random() % (skeleton.num_joints));
4303 if (skeleton.free) {
4304 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4305 flatfacing = skeleton.joints[howmany].position * scale + coords;
4307 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4308 flatvelocity = (coords - oldcoords) / multiplier / 2;
4310 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4313 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4315 howmany = abs(Random() % (skeleton.num_joints));
4316 if (skeleton.free) {
4317 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4318 flatfacing = skeleton.joints[howmany].position * scale + coords;
4320 flatvelocity = (coords - oldcoords) / multiplier / 2;
4321 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4323 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4327 bleeding -= multiplier * .3;
4328 if (bloodtoggle == 2) {
4329 skeleton.drawmodel.textureptr.bind();
4330 if ((bleeding <= 0) && (detail != 2))
4335 if (neckspurtamount > 0) {
4336 neckspurtamount -= multiplier;
4337 neckspurtdelay -= multiplier * 3;
4338 neckspurtparticledelay -= multiplier * 3;
4339 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4342 if (skeleton.free) {
4343 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4344 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4345 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4347 bloodvel.z = 5 * neckspurtamount;
4348 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4349 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4350 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4352 neckspurtparticledelay = .05;
4354 if (neckspurtdelay < 0) {
4359 if (deathbleeding > 0 && dead != 2) {
4360 if (deathbleeding < 5)
4361 bleeddelay -= deathbleeding * multiplier / 4;
4363 bleeddelay -= 5 * multiplier / 4;
4364 if (bleeddelay < 0 && bloodtoggle) {
4369 if (skeleton.free) {
4370 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4371 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4373 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4374 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4378 bloodloss += deathbleeding * multiplier * 80;
4379 deathbleeding -= multiplier * 1.6;
4380 if (deathbleeding < 0)
4382 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4383 if (weaponactive != -1) {
4384 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4385 weapons[weaponids[0]].velocity.x += .01;
4388 weaponids[0] = weaponids[num_weapons];
4389 if (weaponstuck == num_weapons)
4393 for (unsigned i = 0; i < Person::players.size(); i++) {
4394 Person::players[i]->wentforweapon = 0;
4406 if (!dead && creature == wolftype) {
4407 award_bonus(0, Wolfbonus);
4410 if (animTarget == knifefollowedanim && !skeleton.free) {
4411 for (int i = 0; i < skeleton.num_joints; i++) {
4412 skeleton.joints[i].velocity = 0;
4413 skeleton.joints[i].velocity.y = -2;
4416 if (id != 0 && unconscioustime > .1) {
4424 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4425 texupdatedelay = .12;
4427 bloodsize = 5 - realtexdetail;
4431 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4432 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4433 endx = startx + bloodsize;
4434 endy = starty + bloodsize;
4444 if (endx > skeleton.skinsize - 1) {
4445 endx = skeleton.skinsize - 1;
4448 if (endy > skeleton.skinsize - 1) {
4449 endy = skeleton.skinsize - 1;
4457 for (i = startx; i < endx; i++) {
4458 for (j = starty; j < endy; j++) {
4459 if (Random() % 2 == 0) {
4460 color = Random() % 85 + 170;
4461 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4462 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4463 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4464 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4469 skeleton.drawmodel.textureptr.bind();
4473 if (skeleton.free) {
4474 bleedx += 4 * direction / realtexdetail;
4476 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4478 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4480 bleedy -= 4 / realtexdetail;
4482 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4484 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4488 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4489 righthandmorphness = targetrighthandmorphness;
4490 righthandmorphstart = righthandmorphend;
4491 } else if (righthandmorphness > targetrighthandmorphness) {
4492 righthandmorphness -= multiplier * 4;
4493 } else if (righthandmorphness < targetrighthandmorphness) {
4494 righthandmorphness += multiplier * 4;
4497 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4498 lefthandmorphness = targetlefthandmorphness;
4499 lefthandmorphstart = lefthandmorphend;
4500 } else if (lefthandmorphness > targetlefthandmorphness) {
4501 lefthandmorphness -= multiplier * 4;
4502 } else if (lefthandmorphness < targetlefthandmorphness) {
4503 lefthandmorphness += multiplier * 4;
4506 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4507 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4508 tailmorphness = targettailmorphness;
4509 tailmorphstart = tailmorphend;
4510 } else if (tailmorphness > targettailmorphness) {
4511 tailmorphness -= multiplier * 10;
4512 } else if (tailmorphness < targettailmorphness) {
4513 tailmorphness += multiplier * 10;
4517 if (creature == wolftype) {
4518 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4519 tailmorphness = targettailmorphness;
4520 tailmorphstart = tailmorphend;
4521 } else if (tailmorphness > targettailmorphness) {
4522 tailmorphness -= multiplier * 2;
4523 } else if (tailmorphness < targettailmorphness) {
4524 tailmorphness += multiplier * 2;
4528 if (headmorphend == 3 || headmorphstart == 3) {
4529 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4530 headmorphness = targetheadmorphness;
4531 headmorphstart = headmorphend;
4532 } else if (headmorphness > targetheadmorphness) {
4533 headmorphness -= multiplier * 7;
4534 } else if (headmorphness < targetheadmorphness) {
4535 headmorphness += multiplier * 7;
4537 } else if (headmorphend == 5 || headmorphstart == 5) {
4538 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4539 headmorphness = targetheadmorphness;
4540 headmorphstart = headmorphend;
4541 } else if (headmorphness > targetheadmorphness) {
4542 headmorphness -= multiplier * 10;
4543 } else if (headmorphness < targetheadmorphness) {
4544 headmorphness += multiplier * 10;
4547 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4548 headmorphness = targetheadmorphness;
4549 headmorphstart = headmorphend;
4550 } else if (headmorphness > targetheadmorphness) {
4551 headmorphness -= multiplier * 4;
4552 } else if (headmorphness < targetheadmorphness) {
4553 headmorphness += multiplier * 4;
4557 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4558 chestmorphness = targetchestmorphness;
4559 chestmorphstart = chestmorphend;
4560 } else if (chestmorphness > targetchestmorphness) {
4561 chestmorphness -= multiplier;
4562 } else if (chestmorphness < targetchestmorphness) {
4563 chestmorphness += multiplier;
4566 if (dead != 2 && howactive <= typesleeping) {
4567 if (chestmorphstart == 0 && chestmorphend == 0) {
4569 targetchestmorphness = 1;
4572 if (chestmorphstart != 0 && chestmorphend != 0) {
4574 targetchestmorphness = 1;
4576 if (environment == snowyenvironment) {
4579 if (skeleton.free) {
4580 footvel = skeleton.specialforward[0] * -1;
4581 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4583 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4584 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4586 if (animTarget == sleepanim)
4587 footvel = DoRotation(footvel, 0, 90, 0);
4588 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4592 if (!dead && howactive < typesleeping) {
4593 blinkdelay -= multiplier * 2;
4594 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4596 targetheadmorphness = 1;
4598 blinkdelay = (float)(abs(Random() % 40)) / 5;
4600 if (headmorphstart == 3 && headmorphend == 3) {
4602 targetheadmorphness = 1;
4607 twitchdelay -= multiplier * 1.5;
4608 if (animTarget != hurtidleanim) {
4609 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4611 targetheadmorphness = 1;
4613 twitchdelay = (float)(abs(Random() % 40)) / 5;
4615 if (headmorphstart == 5 && headmorphend == 5) {
4617 targetheadmorphness = 1;
4621 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4622 twitchdelay3 -= multiplier * 1;
4623 if (Random() % 2 == 0) {
4624 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4625 righthandmorphness = 0;
4626 targetrighthandmorphness = 1;
4627 righthandmorphend = 1;
4628 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4630 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4631 righthandmorphness = 0;
4632 targetrighthandmorphness = 1;
4633 righthandmorphend = 0;
4636 if (Random() % 2 == 0) {
4637 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4638 lefthandmorphness = 0;
4639 targetlefthandmorphness = 1;
4640 lefthandmorphend = 1;
4641 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4643 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4644 lefthandmorphness = 0;
4645 targetlefthandmorphness = 1;
4646 lefthandmorphend = 0;
4652 if (creature == rabbittype) {
4653 if (howactive < typesleeping)
4654 twitchdelay2 -= multiplier * 1.5;
4656 twitchdelay2 -= multiplier * 0.5;
4657 if (howactive <= typesleeping) {
4658 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4660 targettailmorphness = 1;
4662 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4664 if (tailmorphstart == 1 && tailmorphend == 1) {
4666 targettailmorphness = 1;
4669 if (tailmorphstart == 2 && tailmorphend == 2) {
4671 targettailmorphness = 1;
4678 if (creature == wolftype) {
4679 twitchdelay2 -= multiplier * 1.5;
4680 if (tailmorphend != 0)
4681 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4683 targettailmorphness = 1;
4687 if (tailmorphend != 5)
4688 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4690 targettailmorphness = 1;
4694 if (twitchdelay2 <= 0) {
4695 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4697 targettailmorphness = 1;
4700 if (tailmorphstart == 1 && tailmorphend == 1) {
4702 targettailmorphness = 1;
4705 if (tailmorphstart == 2 && tailmorphend == 2) {
4707 targettailmorphness = 1;
4710 if (tailmorphstart == 3 && tailmorphend == 3) {
4712 targettailmorphness = 1;
4715 if (tailmorphstart == 4 && tailmorphend == 4) {
4717 targettailmorphness = 1;
4724 unconscioustime = 0;
4726 if (dead == 1 || howactive == typesleeping) {
4727 unconscioustime += multiplier;
4728 //If unconscious, close eyes and mouth
4729 if (righthandmorphend != 0)
4730 righthandmorphness = 0;
4731 righthandmorphend = 0;
4732 targetrighthandmorphness = 1;
4734 if (lefthandmorphend != 0)
4735 lefthandmorphness = 0;
4736 lefthandmorphend = 0;
4737 targetlefthandmorphness = 1;
4739 if (headmorphend != 3 && headmorphend != 5)
4742 targetheadmorphness = 1;
4746 if (howactive > typesleeping) {
4749 if (bloodtoggle && !bled) {
4750 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4752 if (bloodtoggle && !bled)
4753 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4754 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4755 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4759 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4764 if (dead == 2 || howactive > typesleeping) {
4765 //If dead, open mouth and hands
4766 if (righthandmorphend != 0)
4767 righthandmorphness = 0;
4768 righthandmorphend = 0;
4769 targetrighthandmorphness = 1;
4771 if (lefthandmorphend != 0)
4772 lefthandmorphness = 0;
4773 lefthandmorphend = 0;
4774 targetlefthandmorphness = 1;
4776 if (headmorphend != 2)
4779 targetheadmorphness = 1;
4782 if (stunned > 0 && !dead && headmorphend != 2) {
4783 if (headmorphend != 4)
4786 targetheadmorphness = 1;
4789 if (damage > damagetolerance && !dead) {
4792 unconscioustime = 0;
4794 if (creature == wolftype) {
4795 award_bonus(0, Wolfbonus);
4800 if (weaponactive != -1) {
4801 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4802 weapons[weaponids[0]].velocity.x += .01;
4805 weaponids[0] = weaponids[num_weapons];
4806 if (weaponstuck == num_weapons)
4810 for (unsigned i = 0; i < Person::players.size(); i++) {
4811 Person::players[i]->wentforweapon = 0;
4817 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4826 damage -= multiplier * 13;
4828 permanentdamage -= multiplier * 4;
4829 if (isIdle() || isCrouch()) {
4831 permanentdamage -= multiplier * 4;
4835 if (permanentdamage < 0)
4836 permanentdamage = 0;
4837 if (superpermanentdamage < 0)
4838 superpermanentdamage = 0;
4839 if (permanentdamage < superpermanentdamage) {
4840 permanentdamage = superpermanentdamage;
4842 if (damage < permanentdamage) {
4843 damage = permanentdamage;
4845 if (dead == 1 && damage < damagetolerance) {
4849 for (int i = 0; i < skeleton.num_joints; i++) {
4850 skeleton.joints[i].velocity = 0;
4853 if (permanentdamage > damagetolerance && dead != 2) {
4856 if (weaponactive != -1) {
4857 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4858 weapons[weaponids[0]].velocity.x += .01;
4861 weaponids[0] = weaponids[num_weapons];
4862 if (weaponstuck == num_weapons)
4866 for (unsigned i = 0; i < Person::players.size(); i++) {
4867 Person::players[i]->wentforweapon = 0;
4873 if (!dead && creature == wolftype) {
4874 award_bonus(0, Wolfbonus);
4877 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4878 award_bonus(id, touchofdeath);
4879 if (id != 0 && unconscioustime > .1) {
4887 emit_sound_at(breaksound, coords);
4890 if (skeleton.free == 1) {
4892 pause_sound(whooshsound);
4895 //If knocked over, open hands and close mouth
4896 if (righthandmorphend != 0)
4897 righthandmorphness = 0;
4898 righthandmorphend = 0;
4899 targetrighthandmorphness = 1;
4901 if (lefthandmorphend != 0)
4902 lefthandmorphness = 0;
4903 lefthandmorphend = 0;
4904 targetlefthandmorphness = 1;
4906 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4907 if (headmorphend != 0)
4910 targetheadmorphness = 1;
4914 skeleton.DoGravity(&scale);
4916 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4917 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4918 award_bonus(id, deepimpact);
4919 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4923 for (j = 0; j < skeleton.num_joints; j++) {
4924 average += skeleton.joints[j].position;
4928 coords += average * scale;
4929 for (j = 0; j < skeleton.num_joints; j++) {
4930 skeleton.joints[j].position -= average;
4932 average /= multiplier;
4935 for (int i = 0; i < skeleton.num_joints; i++) {
4936 velocity += skeleton.joints[i].velocity * scale;
4938 velocity /= skeleton.num_joints;
4940 if (!isnormal(velocity.x) && velocity.x) {
4944 if (findLength(&average) < 10 && dead && skeleton.free) {
4945 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4946 if (skeleton.longdead > 2000) {
4947 if (skeleton.longdead > 6000) {
4949 pause_sound(whooshsound);
4954 if (dead == 2 && bloodloss < damagetolerance) {
4956 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4958 if (bloodtoggle && !bled) {
4959 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4961 if (bloodtoggle && !bled)
4962 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4963 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4964 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4965 float size = .2 * 1.2;
4968 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4972 if (dead == 2 && bloodloss >= damagetolerance) {
4974 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4977 if (bloodtoggle && !bled) {
4978 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4980 if (bloodtoggle && !bled)
4981 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4982 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4983 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4987 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4994 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4995 bool canrecover = 1;
4996 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4997 startpoint = coords;
5000 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5002 if (velocity.y < -30)
5004 for (i = 0; i < objects.numobjects; i++) {
5005 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5006 colviewer = startpoint;
5007 coltarget = endpoint;
5008 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5017 terrainnormal = jointPos(groin) - jointPos(abdomen);
5018 if (joint(groin).locked && joint(abdomen).locked) {
5019 terrainnormal = jointPos(groin) - jointPos(abdomen);
5020 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5022 if (joint(abdomen).locked && joint(neck).locked) {
5023 terrainnormal = jointPos(abdomen) - jointPos(neck);
5024 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5026 if (joint(groin).locked && joint(neck).locked) {
5027 terrainnormal = jointPos(groin) - jointPos(neck);
5028 middle = (jointPos(groin) + jointPos(neck)) / 2;
5030 Normalise(&terrainnormal);
5032 targetyaw = -asin(0 - terrainnormal.x);
5033 targetyaw *= 360 / 6.28;
5034 if (terrainnormal.z < 0)
5035 targetyaw = 180 - targetyaw;
5039 animTarget = flipanim;
5040 crouchtogglekeydown = 1;
5045 animCurrent = tempanim;
5049 for (int i = 0; i < skeleton.num_joints; i++) {
5050 tempanimation.position[i][0] = skeleton.joints[i].position;
5051 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5056 if (findLength(&average) < 10 && !dead && skeleton.free) {
5057 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5058 if (skeleton.longdead > (damage + 500) * 1.5) {
5060 pause_sound(whooshsound);
5066 terrainnormal = jointPos(groin) - jointPos(abdomen);
5067 if (joint(groin).locked && joint(abdomen).locked) {
5068 terrainnormal = jointPos(groin) - jointPos(abdomen);
5069 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5071 if (joint(abdomen).locked && joint(neck).locked) {
5072 terrainnormal = jointPos(abdomen) - jointPos(neck);
5073 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5075 if (joint(groin).locked && joint(neck).locked) {
5076 terrainnormal = jointPos(groin) - jointPos(neck);
5077 middle = (jointPos(groin) + jointPos(neck)) / 2;
5079 Normalise(&terrainnormal);
5081 targetyaw = -asin(0 - terrainnormal.x);
5082 targetyaw *= 360 / 6.28;
5083 if (terrainnormal.z < 0)
5084 targetyaw = 180 - targetyaw;
5087 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5090 if (skeleton.forward.y < 0) {
5091 animTarget = getupfrombackanim;
5095 if (skeleton.forward.y > -.3) {
5096 animTarget = getupfromfrontanim;
5104 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5105 animTarget = rollanim;
5106 targetyaw = lookyaw;
5123 if ( !leftkeydown && !rightkeydown)
5130 if (abs(targettilt2) > 50)
5132 animCurrent = tempanim;
5135 tilt2 = targettilt2;
5137 if (middle.y > 0 && animTarget != rollanim)
5138 targetoffset.y = middle.y + 1;
5140 for (int i = 0; i < skeleton.num_joints; i++) {
5141 tempanimation.position[i][0] = skeleton.joints[i].position;
5142 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5149 if (num_weapons > 0)
5150 if (weapons[0].getType() == staff)
5152 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5153 if (velocity.y > -30) {
5155 tempvelocity = velocity;
5156 Normalise(&tempvelocity);
5157 targetyaw = -asin(0 - tempvelocity.x);
5158 targetyaw *= 360 / 6.28;
5160 targetyaw = 180 - targetyaw;
5164 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5165 animTarget = rollanim;
5168 animTarget = backhandspringanim;
5174 emit_sound_at(movewhooshsound, coords, 128.);
5176 animCurrent = animTarget;
5177 frameCurrent = frameTarget - 1;
5189 if (skeleton.freefall == 0)
5194 if (aitype != passivetype || skeleton.free == 1)
5195 if (findLengthfast(&velocity) > .1)
5196 for (i = 0; i < objects.numobjects; i++) {
5197 if (objects.type[i] == firetype)
5198 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) {
5200 if (!objects.onfire[i]) {
5201 emit_sound_at(firestartsound, objects.position[i]);
5203 objects.onfire[i] = 1;
5206 if (objects.onfire[i]) {
5211 if (objects.type[i] == bushtype)
5212 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) {
5214 if (!objects.onfire[i]) {
5215 emit_sound_at(firestartsound, objects.position[i]);
5217 objects.onfire[i] = 1;
5221 if (objects.onfire[i]) {
5225 if (objects.messedwith[i] <= 0) {
5229 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5232 envsound[numenvsounds] = coords;
5233 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5234 envsoundlife[numenvsounds] = .4;
5239 if (environment == grassyenvironment)
5240 howmany = findLength(&velocity) * 4;
5241 if (environment == snowyenvironment)
5242 howmany = findLength(&velocity) * 2;
5244 if (environment != desertenvironment)
5245 for (j = 0; j < howmany; j++) {
5246 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5247 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5248 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5251 pos.x += float(abs(Random() % 100) - 50) / 200;
5252 pos.y += float(abs(Random() % 100) - 50) / 200;
5253 pos.z += float(abs(Random() % 100) - 50) / 200;
5254 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);
5255 Sprite::setLastSpriteSpecial(1);
5257 howmany = findLength(&velocity) * 4;
5259 if (environment == snowyenvironment)
5260 for (j = 0; j < howmany; j++) {
5261 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5262 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5263 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5266 pos.x += float(abs(Random() % 100) - 50) / 200;
5267 pos.y += float(abs(Random() % 100) - 50) / 200;
5268 pos.z += float(abs(Random() % 100) - 50) / 200;
5269 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5270 Sprite::setLastSpriteSpecial(2);
5273 objects.rotx[i] += velocity.x * multiplier * 6;
5274 objects.roty[i] += velocity.z * multiplier * 6;
5275 objects.messedwith[i] = .5;
5278 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5279 if (objects.pitch[i] == 0)
5282 tempcoord = coords - objects.position[i];
5283 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5284 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5285 tempcoord += objects.position[i];
5287 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]) {
5288 if (objects.messedwith[i] <= 0) {
5292 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5295 envsound[numenvsounds] = coords;
5296 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5297 envsoundlife[numenvsounds] = .4;
5302 if (environment == grassyenvironment)
5303 howmany = findLength(&velocity) * 4;
5304 if (environment == snowyenvironment)
5305 howmany = findLength(&velocity) * 2;
5307 if (environment != desertenvironment)
5308 for (j = 0; j < howmany; j++) {
5309 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5310 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5311 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5313 pos += velocity * .1;
5315 pos.x += float(abs(Random() % 100) - 50) / 150;
5316 pos.y += float(abs(Random() % 100) - 50) / 150;
5317 pos.z += float(abs(Random() % 100) - 50) / 150;
5318 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);
5319 Sprite::setLastSpriteSpecial(1);
5321 howmany = findLength(&velocity) * 4;
5323 if (environment == snowyenvironment)
5324 for (j = 0; j < howmany; j++) {
5325 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5326 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5327 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5329 pos += velocity * .1;
5331 pos.x += float(abs(Random() % 100) - 50) / 150;
5332 pos.y += float(abs(Random() % 100) - 50) / 150;
5333 pos.z += float(abs(Random() % 100) - 50) / 150;
5334 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5335 Sprite::setLastSpriteSpecial(2);
5338 objects.messedwith[i] = .5;
5343 if (!skeleton.free) {
5346 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5349 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5351 if (tutoriallevel == 1 && id != 0)
5353 if (play && aitype != playercontrolled) {
5354 int whichsound = -1;
5355 i = abs(Random() % 4);
5356 if (speechdelay <= 0) {
5357 if (creature == rabbittype) {
5359 whichsound = rabbitchitter;
5361 whichsound = rabbitchitter2;
5363 if (creature == wolftype) {
5365 whichsound = growlsound;
5367 whichsound = growl2sound;
5372 if (whichsound != -1) {
5373 emit_sound_at(whichsound, coords);
5377 if (animTarget == staggerbackhighanim)
5379 if (animTarget == staggerbackhardanim)
5381 staggerdelay -= multiplier;
5382 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5384 if (velocity.y < -30 && animTarget == jumpdownanim)
5386 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5387 animTarget = getIdle();
5391 weaponmissdelay -= multiplier;
5392 highreversaldelay -= multiplier;
5393 lowreversaldelay -= multiplier;
5394 lastcollide -= multiplier;
5395 skiddelay -= multiplier;
5396 if (!isnormal(velocity.x) && velocity.x) {
5399 if (!isnormal(targettilt) && targettilt) {
5402 if (!isnormal(targettilt2) && targettilt2) {
5405 if (!isnormal(targetyaw) && targetyaw) {
5409 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5410 //open hands and close mouth
5411 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5412 righthandmorphness = 0;
5413 righthandmorphend = 0;
5414 targetrighthandmorphness = 1;
5417 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5418 lefthandmorphness = 0;
5419 lefthandmorphend = 0;
5420 targetlefthandmorphness = 1;
5423 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5426 targetheadmorphness = 1;
5430 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) {
5431 //open hands and mouth
5432 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5433 righthandmorphness = 0;
5434 righthandmorphend = 0;
5435 targetrighthandmorphness = 1;
5438 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5439 lefthandmorphness = 0;
5440 lefthandmorphend = 0;
5441 targetlefthandmorphness = 1;
5444 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5447 targetheadmorphness = 1;
5451 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5452 //close hands and mouth
5453 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5454 righthandmorphness = 0;
5455 righthandmorphend = 1;
5456 targetrighthandmorphness = 1;
5459 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5460 lefthandmorphness = 0;
5461 lefthandmorphend = 1;
5462 targetlefthandmorphness = 1;
5465 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5468 targetheadmorphness = 1;
5472 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) {
5473 //close hands and yell
5474 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5475 righthandmorphness = 0;
5476 righthandmorphend = 1;
5477 targetrighthandmorphness = 1;
5480 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5481 lefthandmorphness = 0;
5482 lefthandmorphend = 1;
5483 targetlefthandmorphness = 1;
5486 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5489 targetheadmorphness = 1;
5496 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5497 (victim->aitype != searchtype) && (aitype != passivetype) &&
5498 (aitype != searchtype) && (victim->id < Person::players.size())) {
5499 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5503 if (!dead && animTarget != hurtidleanim)
5504 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5505 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5508 targetheadmorphness = 1;
5512 if (weaponactive != -1) {
5513 if (weapons[weaponids[weaponactive]].getType() != staff) {
5514 righthandmorphstart = 1;
5515 righthandmorphend = 1;
5517 if (weapons[weaponids[weaponactive]].getType() == staff) {
5518 righthandmorphstart = 2;
5519 righthandmorphend = 2;
5521 targetrighthandmorphness = 1;
5524 terrainnormal = terrain.getNormal(coords.x, coords.z);
5526 if (animation[animTarget].attack != reversal) {
5527 if (!isnormal(coords.x))
5535 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5536 facing = flatfacing;
5537 ReflectVector(&facing, terrainnormal);
5540 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5542 targettilt2 = -facing.y * 20;
5547 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5549 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5550 flatvelocity = velocity;
5552 flatvelspeed = findLength(&flatvelocity);
5553 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5554 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5559 if (targettilt > 25)
5561 if (targettilt < -25)
5565 if (targettilt2 > 45)
5567 if (targettilt2 < -45)
5569 if (abs(tilt2 - targettilt2) < multiplier * 400)
5570 tilt2 = targettilt2;
5571 else if (tilt2 > targettilt2) {
5572 tilt2 -= multiplier * 400;
5573 } else if (tilt2 < targettilt2) {
5574 tilt2 += multiplier * 400;
5576 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5583 if (!isnormal(targettilt) && targettilt) {
5586 if (!isnormal(targettilt2) && targettilt2) {
5591 if (animTarget == rabbittackleanim) {
5592 velocity += facing * multiplier * speed * 700 * scale;
5593 velspeed = findLength(&velocity);
5594 if (velspeed > speed * 65 * scale) {
5595 velocity /= velspeed;
5596 velspeed = speed * 65 * scale;
5597 velocity *= velspeed;
5599 velocity.y += gravity * multiplier * 20;
5600 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5601 velspeed = findLength(&velocity);
5602 velocity = flatfacing * velspeed;
5604 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5605 if (isRun() || animTarget == rabbitkickanim) {
5606 velocity += facing * multiplier * speed * 700 * scale;
5607 velspeed = findLength(&velocity);
5608 if (velspeed > speed * 45 * scale) {
5609 velocity /= velspeed;
5610 velspeed = speed * 45 * scale;
5611 velocity *= velspeed;
5613 velocity.y += gravity * multiplier * 20;
5614 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5615 velspeed = findLength(&velocity);
5616 if (velspeed < speed * 30 * scale)
5617 velspeed = speed * 30 * scale;
5618 velocity = flatfacing * velspeed;
5620 } else if (isRun()) {
5621 velocity += facing * multiplier * speed * 700 * scale;
5622 velspeed = findLength(&velocity);
5623 if (creature == rabbittype) {
5624 if (velspeed > speed * 55 * scale) {
5625 velocity /= velspeed;
5626 velspeed = speed * 55 * scale;
5627 velocity *= velspeed;
5630 if (creature == wolftype) {
5631 if (velspeed > speed * 75 * scale) {
5632 velocity /= velspeed;
5633 velspeed = speed * 75 * scale;
5634 velocity *= velspeed;
5637 velocity.y += gravity * multiplier * 20;
5638 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5639 velspeed = findLength(&velocity);
5640 velocity = flatfacing * velspeed;
5643 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5644 velocity += facing * multiplier * speed * 700 * scale;
5645 velspeed = findLength(&velocity);
5646 if (velspeed > speed * 45 * scale) {
5647 velocity /= velspeed;
5648 velspeed = speed * 45 * scale;
5649 velocity *= velspeed;
5651 velocity.y += gravity * multiplier * 20;
5652 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5653 velspeed = findLength(&velocity);
5654 velocity = flatfacing * velspeed;
5657 if (animTarget == sneakanim || animTarget == walkanim) {
5658 velocity += facing * multiplier * speed * 700 * scale;
5659 velspeed = findLength(&velocity);
5660 if (velspeed > speed * 12 * scale) {
5661 velocity /= velspeed;
5662 velspeed = speed * 12 * scale;
5663 velocity *= velspeed;
5665 velocity.y += gravity * multiplier * 20;
5666 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5667 velspeed = findLength(&velocity);
5668 velocity = flatfacing * velspeed;
5671 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5672 velocity += facing * multiplier * speed * 700 * scale;
5673 velspeed = findLength(&velocity);
5674 if (velspeed > speed * 2 * scale) {
5675 velocity /= velspeed;
5676 velspeed = speed * 2 * scale;
5677 velocity *= velspeed;
5679 velocity.y += gravity * multiplier * 20;
5680 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5681 velspeed = findLength(&velocity);
5682 velocity = flatfacing * velspeed;
5686 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5687 velocity -= facing * multiplier * speed * 700 * scale;
5688 velspeed = findLength(&velocity);
5689 if (velspeed > speed * 2 * scale) {
5690 velocity /= velspeed;
5691 velspeed = speed * 2 * scale;
5692 velocity *= velspeed;
5694 velocity.y += gravity * multiplier * 20;
5695 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5696 velspeed = findLength(&velocity);
5697 velocity = flatfacing * velspeed * -1;
5700 if (animTarget == fightsidestep) {
5701 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5702 velspeed = findLength(&velocity);
5703 if (velspeed > speed * 12 * scale) {
5704 velocity /= velspeed;
5705 velspeed = speed * 12 * scale;
5706 velocity *= velspeed;
5708 velocity.y += gravity * multiplier * 20;
5709 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5710 velspeed = findLength(&velocity);
5711 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5714 if (animTarget == staggerbackhighanim) {
5715 coords -= facing * multiplier * speed * 16 * scale;
5718 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5719 coords -= facing * multiplier * speed * 20 * scale;
5723 if (animTarget == backhandspringanim) {
5724 //coords-=facing*multiplier*50*scale;
5725 velocity += facing * multiplier * speed * 700 * scale * -1;
5726 velspeed = findLength(&velocity);
5727 if (velspeed > speed * 50 * scale) {
5728 velocity /= velspeed;
5729 velspeed = speed * 50 * scale;
5730 velocity *= velspeed;
5732 velocity.y += gravity * multiplier * 20;
5733 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5734 velspeed = findLength(&velocity);
5735 velocity = flatfacing * velspeed * -1;
5737 if (animTarget == dodgebackanim) {
5738 //coords-=facing*multiplier*50*scale;
5739 velocity += facing * multiplier * speed * 700 * scale * -1;
5740 velspeed = findLength(&velocity);
5741 if (velspeed > speed * 60 * scale) {
5742 velocity /= velspeed;
5743 velspeed = speed * 60 * scale;
5744 velocity *= velspeed;
5746 velocity.y += gravity * multiplier * 20;
5747 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5748 velspeed = findLength(&velocity);
5749 velocity = flatfacing * velspeed * -1;
5752 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5753 velspeed = findLength(&velocity);
5757 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5758 velocity.y += gravity * multiplier;
5761 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5762 coords += velocity * multiplier;
5764 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5765 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5768 if (animTarget == jumpupanim) {
5770 animTarget = getIdle();
5777 pause_sound(whooshsound);
5778 OPENAL_SetVolume(channels[whooshsound], 0);
5781 if (animTarget == jumpdownanim || isFlip()) {
5782 if (isFlip())jumppower = -4;
5783 animTarget = getLanding();
5784 emit_sound_at(landsound, coords, 128.);
5787 envsound[numenvsounds] = coords;
5788 envsoundvol[numenvsounds] = 16;
5789 envsoundlife[numenvsounds] = .4;
5795 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5796 coords.y += gravity * multiplier * 2;
5797 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5798 coords.y = terrain.getHeight(coords.x, coords.z);
5803 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)) {
5804 velspeed = findLength(&velocity);
5806 if (velspeed < multiplier * 300 * scale) {
5809 velocity -= velocity / velspeed * multiplier * 300 * scale;
5810 if (velspeed > 5 && (isLanding() || isLandhard())) {
5811 skiddingdelay += multiplier;
5812 if (skiddelay <= 0) {
5822 velspeed = findLength(&velocity);
5824 if (velspeed < multiplier * 600 * scale) {
5827 velocity -= velocity / velspeed * multiplier * 600 * scale;
5829 if (velspeed > 5 && (isLanding() || isLandhard())) {
5830 skiddingdelay += multiplier;
5831 if (skiddelay <= 0) {
5840 if (skiddingdelay < 0)
5841 skiddingdelay += multiplier;
5842 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5844 if (!onterrain || environment == grassyenvironment) {
5845 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5847 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5851 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5852 terrainnormal = victim->coords - coords;
5853 Normalise(&terrainnormal);
5854 targetyaw = -asin(0 - terrainnormal.x);
5855 targetyaw *= 360 / 6.28;
5856 if (terrainnormal.z < 0)
5857 targetyaw = 180 - targetyaw;
5858 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5861 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5862 targetyaw = victim->targetyaw;
5864 if (animTarget == rabbittacklinganim) {
5865 coords = victim->coords;
5868 skeleton.oldfree = skeleton.free;
5872 midterrain.x = terrain.size * terrain.scale / 2;
5873 midterrain.z = terrain.size * terrain.scale / 2;
5874 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5876 tempposit = coords - midterrain;
5878 Normalise(&tempposit);
5879 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5880 coords.x = tempposit.x + midterrain.x;
5881 coords.z = tempposit.z + midterrain.z;
5887 * inverse kinematics helper function
5889 void IKHelper(Person *p, float interp)
5891 XYZ point, change, change2;
5892 float heightleft, heightright;
5894 // TODO: implement localToWorld and worldToLocal
5895 // but keep in mind it won't be the same math if player is ragdolled or something
5896 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5897 // then comb through code for places where to use it
5899 // point = localToWorld(jointPos(leftfoot))
5900 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5901 // adjust height of foot
5902 heightleft = terrain.getHeight(point.x, point.z) + .04;
5903 point.y = heightleft;
5904 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5905 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5906 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5907 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5908 // move ankle along with foot
5909 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5910 // average knee pos between old and new pos
5911 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5913 // do same as above for right leg
5914 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5915 heightright = terrain.getHeight(point.x, point.z) + .04;
5916 point.y = heightright;
5917 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5918 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5919 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5920 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5921 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5923 // fix up skeleton now that we've moved body parts?
5924 p->skeleton.DoConstraints(&p->coords, &p->scale);
5931 int Person::DrawSkeleton()
5933 int oldplayerdetail;
5934 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5935 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5945 glAlphaFunc(GL_GREATER, 0.0001);
5947 float terrainheight;
5951 if (!isnormal(tilt))
5953 if (!isnormal(tilt2))
5955 oldplayerdetail = playerdetail;
5957 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5960 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5963 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5968 if (playerdetail != oldplayerdetail) {
5970 normalsupdatedelay = 0;
5972 static float updatedelaychange;
5973 static float morphness;
5974 static float framemult;
5976 skeleton.FindForwards();
5977 if (howactive == typesittingwall) {
5978 skeleton.specialforward[1] = 0;
5979 skeleton.specialforward[1].z = 1;
5985 static int weaponattachmuscle;
5986 static int weaponrotatemuscle;
5987 static XYZ weaponpoint;
5988 static int start, endthing;
5989 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5990 if (!isSleeping() && !isSitting()) {
5991 // TODO: give these meaningful names
5992 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5993 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5994 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5995 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5997 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5999 if (creature == wolftype)
6003 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6004 IKHelper(this, target);
6005 if (creature == wolftype)
6006 IKHelper(this, target);
6009 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6010 IKHelper(this, 1 - target);
6011 if (creature == wolftype)
6012 IKHelper(this, 1 - target);
6016 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()))
6019 targetheadyaw = -targetyaw;
6020 targetheadpitch = 0;
6021 if (animation[animTarget].attack == 3)
6022 targetheadyaw += 180;
6024 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6025 skeleton.drawmodel.vertex[i] = 0;
6026 skeleton.drawmodel.vertex[i].y = 999;
6028 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6029 skeleton.drawmodellow.vertex[i] = 0;
6030 skeleton.drawmodellow.vertex[i].y = 999;
6032 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6033 skeleton.drawmodelclothes.vertex[i] = 0;
6034 skeleton.drawmodelclothes.vertex[i].y = 999;
6036 for (int i = 0; i < skeleton.num_muscles; i++) {
6037 // convenience renames
6038 const int p1 = skeleton.muscles[i].parent1->label;
6039 const int p2 = skeleton.muscles[i].parent2->label;
6041 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6046 if (p1 == righthand || p2 == righthand) {
6047 morphness = righthandmorphness;
6048 start = righthandmorphstart;
6049 endthing = righthandmorphend;
6051 if (p1 == lefthand || p2 == lefthand) {
6052 morphness = lefthandmorphness;
6053 start = lefthandmorphstart;
6054 endthing = lefthandmorphend;
6056 if (p1 == head || p2 == head) {
6057 morphness = headmorphness;
6058 start = headmorphstart;
6059 endthing = headmorphend;
6061 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6062 morphness = chestmorphness;
6063 start = chestmorphstart;
6064 endthing = chestmorphend;
6066 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6067 morphness = tailmorphness;
6068 start = tailmorphstart;
6069 endthing = tailmorphend;
6072 skeleton.FindRotationMuscle(i, animTarget);
6073 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6074 glMatrixMode(GL_MODELVIEW);
6078 glRotatef(tilt2, 1, 0, 0);
6080 glRotatef(tilt, 0, 0, 1);
6083 glTranslatef(mid.x, mid.y, mid.z);
6085 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6086 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6088 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6089 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6091 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6092 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6094 if (playerdetail || skeleton.free == 3) {
6095 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6096 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6097 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6098 glMatrixMode(GL_MODELVIEW);
6100 if (p1 == abdomen || p2 == abdomen)
6101 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6102 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6103 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6104 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6105 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6106 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6107 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6108 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6109 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6110 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6111 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6112 if (p1 == head || p2 == head)
6113 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6114 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6115 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6116 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6117 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6118 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6119 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6123 if (!playerdetail || skeleton.free == 3) {
6124 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6125 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6126 glMatrixMode(GL_MODELVIEW);
6128 if (p1 == abdomen || p2 == abdomen)
6129 glTranslatef(v0.x * proportionbody.x,
6130 v0.y * proportionbody.y,
6131 v0.z * proportionbody.z);
6132 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6133 glTranslatef(v0.x * proportionarms.x,
6134 v0.y * proportionarms.y,
6135 v0.z * proportionarms.z);
6136 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6137 glTranslatef(v0.x * proportionlegs.x,
6138 v0.y * proportionlegs.y,
6139 v0.z * proportionlegs.z);
6140 if (p1 == head || p2 == head)
6141 glTranslatef(v0.x * proportionhead.x,
6142 v0.y * proportionhead.y,
6143 v0.z * proportionhead.z);
6145 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6146 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6147 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6148 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6154 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6155 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6157 glMatrixMode(GL_MODELVIEW);
6161 glRotatef(tilt2, 1, 0, 0);
6163 glRotatef(tilt, 0, 0, 1);
6164 glTranslatef(mid.x, mid.y, mid.z);
6165 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6166 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6168 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6169 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6171 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6172 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6174 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6175 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6176 glMatrixMode(GL_MODELVIEW);
6178 if (p1 == abdomen || p2 == abdomen)
6179 glTranslatef(v0.x * proportionbody.x,
6180 v0.y * proportionbody.y,
6181 v0.z * proportionbody.z);
6182 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6183 glTranslatef(v0.x * proportionarms.x,
6184 v0.y * proportionarms.y,
6185 v0.z * proportionarms.z);
6186 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6187 glTranslatef(v0.x * proportionlegs.x,
6188 v0.y * proportionlegs.y,
6189 v0.z * proportionlegs.z);
6190 if (p1 == head || p2 == head)
6191 glTranslatef(v0.x * proportionhead.x,
6192 v0.y * proportionhead.y,
6193 v0.z * proportionhead.z);
6194 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6195 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6196 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6197 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6202 updatedelay = 1 + (float)(Random() % 100) / 1000;
6204 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6205 normalsupdatedelay = 1;
6206 if (playerdetail || skeleton.free == 3)
6207 skeleton.drawmodel.CalculateNormals(0);
6208 if (!playerdetail || skeleton.free == 3)
6209 skeleton.drawmodellow.CalculateNormals(0);
6210 if (skeleton.clothes)
6211 skeleton.drawmodelclothes.CalculateNormals(0);
6213 if (playerdetail || skeleton.free == 3)
6214 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6215 if (!playerdetail || skeleton.free == 3)
6216 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6217 if (skeleton.clothes) {
6218 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6223 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6224 if (updatedelaychange > -realmultiplier * 30)
6225 updatedelaychange = -realmultiplier * 30;
6226 if (updatedelaychange > -framemult * 4)
6227 updatedelaychange = -framemult * 4;
6228 if (skeleton.free == 1)
6229 updatedelaychange *= 6;
6231 updatedelaychange *= 8;
6232 updatedelay += updatedelaychange;
6234 glMatrixMode(GL_MODELVIEW);
6236 glTranslatef(coords.x, coords.y - .02, coords.z);
6237 if (!skeleton.free) {
6238 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6239 glRotatef(yaw, 0, 1, 0);
6243 glColor4f(.4, 1, .4, 1);
6244 glDisable(GL_LIGHTING);
6245 glDisable(GL_TEXTURE_2D);
6248 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6249 XYZ &v0 = skeleton.drawmodel.vertex[i];
6250 glVertex3f(v0.x, v0.y, v0.z);
6256 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6257 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6258 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6259 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6260 glVertex3f(v0.x, v0.y, v0.z);
6261 glVertex3f(v1.x, v1.y, v1.z);
6262 glVertex3f(v1.x, v1.y, v1.z);
6263 glVertex3f(v2.x, v2.y, v2.z);
6264 glVertex3f(v2.x, v2.y, v2.z);
6265 glVertex3f(v0.x, v0.y, v0.z);
6271 terrainlight = terrain.getLighting(coords.x, coords.z);
6272 distance = distsq(&viewer, &coords);
6273 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6277 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6278 if (terrainheight < 1)
6280 if (terrainheight > 1.7)
6281 terrainheight = 1.7;
6284 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6285 glDisable(GL_BLEND);
6286 glAlphaFunc(GL_GREATER, 0.0001);
6287 glEnable(GL_TEXTURE_2D);
6289 glDisable(GL_TEXTURE_2D);
6290 glColor4f(.7, .35, 0, .5);
6292 glEnable(GL_LIGHTING);
6295 if (tutoriallevel && id != 0) {
6296 glColor4f(.7, .7, .7, 0.6);
6298 glEnable(GL_LIGHTING);
6300 if (canattack && cananger)
6301 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6302 glDisable(GL_TEXTURE_2D);
6303 glColor4f(1, 0, 0, 0.8);
6305 glMatrixMode(GL_TEXTURE);
6307 glTranslatef(0, -smoketex, 0);
6308 glTranslatef(-smoketex, 0, 0);
6312 if ((tutoriallevel && id != 0))
6313 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6315 skeleton.drawmodel.draw();
6318 if (!playerdetail) {
6319 if ((tutoriallevel && id != 0))
6320 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6322 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6325 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6326 if (tutoriallevel && id != 0) {
6328 glMatrixMode(GL_MODELVIEW);
6329 glEnable(GL_TEXTURE_2D);
6330 glColor4f(.7, .7, .7, 0.6);
6332 glEnable(GL_LIGHTING);
6334 if (canattack && cananger)
6335 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6336 glDisable(GL_TEXTURE_2D);
6337 glColor4f(1, 0, 0, 0.8);
6339 glMatrixMode(GL_TEXTURE);
6341 glTranslatef(0, -smoketex * .6, 0);
6342 glTranslatef(smoketex * .6, 0, 0);
6345 if ((tutoriallevel && id != 0))
6346 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6348 skeleton.drawmodel.draw();
6351 if (!playerdetail) {
6352 if ((tutoriallevel && id != 0))
6353 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6355 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6360 if (tutoriallevel && id != 0) {
6362 glMatrixMode(GL_MODELVIEW);
6363 glEnable(GL_TEXTURE_2D);
6365 if (skeleton.clothes) {
6369 skeleton.drawmodelclothes.draw();
6371 skeleton.drawmodelclothes.drawimmediate();
6377 if (num_weapons > 0) {
6378 for (k = 0; k < num_weapons; k++) {
6380 if (weaponactive == k) {
6381 if (weapons[i].getType() != staff) {
6382 for (j = 0; j < skeleton.num_muscles; j++) {
6383 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6384 weaponattachmuscle = j;
6387 for (j = 0; j < skeleton.num_muscles; j++) {
6388 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) {
6389 weaponrotatemuscle = j;
6392 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6393 if (creature == wolftype)
6394 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6396 if (weapons[i].getType() == staff) {
6397 for (j = 0; j < skeleton.num_muscles; j++) {
6398 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6399 weaponattachmuscle = j;
6402 for (j = 0; j < skeleton.num_muscles; j++) {
6403 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) {
6404 weaponrotatemuscle = j;
6407 //weaponpoint=jointPos(rightwrist);
6408 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6409 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6410 XYZ tempnormthing, vec1, vec2;
6411 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6412 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6413 CrossProduct(&vec1, &vec2, &tempnormthing);
6414 Normalise(&tempnormthing);
6415 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6416 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6419 if (weaponactive != k && weaponstuck != k) {
6420 if (weapons[i].getType() == knife)
6421 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6422 if (weapons[i].getType() == sword)
6423 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6424 if (weapons[i].getType() == staff)
6425 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6426 for (j = 0; j < skeleton.num_muscles; j++) {
6427 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) {
6428 weaponrotatemuscle = j;
6432 if (weaponstuck == k) {
6433 if (weaponstuckwhere == 0)
6434 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6436 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6437 for (j = 0; j < skeleton.num_muscles; j++) {
6438 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) {
6439 weaponrotatemuscle = j;
6443 if (skeleton.free) {
6444 weapons[i].position = weaponpoint * scale + coords;
6445 weapons[i].bigrotation = 0;
6446 weapons[i].bigtilt = 0;
6447 weapons[i].bigtilt2 = 0;
6449 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;
6450 weapons[i].bigrotation = yaw;
6451 weapons[i].bigtilt = tilt;
6452 weapons[i].bigtilt2 = tilt2;
6454 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6455 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6456 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6457 if (weaponactive == k) {
6458 if (weapons[i].getType() == knife) {
6459 weapons[i].smallrotation = 180;
6460 weapons[i].smallrotation2 = 0;
6461 if (isCrouch() || wasCrouch()) {
6462 weapons[i].smallrotation2 = 20;
6464 if (animTarget == hurtidleanim) {
6465 weapons[i].smallrotation2 = 50;
6467 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6468 XYZ temppoint1, temppoint2;
6471 temppoint1 = jointPos(righthand);
6472 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6473 distance = findDistance(&temppoint1, &temppoint2);
6474 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6475 weapons[i].rotation2 *= 360 / 6.28;
6478 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6479 weapons[i].rotation1 *= 360 / 6.28;
6480 weapons[i].rotation3 = 0;
6481 weapons[i].smallrotation = -90;
6482 weapons[i].smallrotation2 = 0;
6483 if (temppoint1.x > temppoint2.x)
6484 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6486 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6487 XYZ temppoint1, temppoint2;
6490 temppoint1 = jointPos(righthand);
6491 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6492 distance = findDistance(&temppoint1, &temppoint2);
6493 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6494 weapons[i].rotation2 *= 360 / 6.28;
6497 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6498 weapons[i].rotation1 *= 360 / 6.28;
6499 weapons[i].rotation3 = 0;
6500 weapons[i].smallrotation = 90;
6501 weapons[i].smallrotation2 = 0;
6502 if (temppoint1.x > temppoint2.x)
6503 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6505 if (animTarget == knifethrowanim) {
6506 weapons[i].smallrotation = 90;
6507 //weapons[i].smallrotation2=-90;
6508 weapons[i].smallrotation2 = 0;
6509 weapons[i].rotation1 = 0;
6510 weapons[i].rotation2 = 0;
6511 weapons[i].rotation3 = 0;
6513 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6514 weapons[i].smallrotation = -90;
6515 weapons[i].rotation1 = 0;
6516 weapons[i].rotation2 = 0;
6517 weapons[i].rotation3 = 0;
6520 if (weapons[i].getType() == sword) {
6521 weapons[i].smallrotation = 0;
6522 weapons[i].smallrotation2 = 0;
6523 if (animTarget == knifethrowanim) {
6524 weapons[i].smallrotation = -90;
6525 weapons[i].smallrotation2 = 0;
6526 weapons[i].rotation1 = 0;
6527 weapons[i].rotation2 = 0;
6528 weapons[i].rotation3 = 0;
6530 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)) {
6531 XYZ temppoint1, temppoint2;
6534 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6535 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6536 distance = findDistance(&temppoint1, &temppoint2);
6537 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6538 weapons[i].rotation2 *= 360 / 6.28;
6541 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6542 weapons[i].rotation1 *= 360 / 6.28;
6543 weapons[i].rotation3 = 0;
6544 weapons[i].smallrotation = 90;
6545 weapons[i].smallrotation2 = 0;
6546 if (temppoint1.x > temppoint2.x)
6547 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6550 if (weapons[i].getType() == staff) {
6551 weapons[i].smallrotation = 100;
6552 weapons[i].smallrotation2 = 0;
6553 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6554 XYZ temppoint1, temppoint2;
6557 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6558 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6559 distance = findDistance(&temppoint1, &temppoint2);
6560 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6561 weapons[i].rotation2 *= 360 / 6.28;
6564 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6565 weapons[i].rotation1 *= 360 / 6.28;
6566 weapons[i].rotation3 = 0;
6567 weapons[i].smallrotation = 90;
6568 weapons[i].smallrotation2 = 0;
6569 if (temppoint1.x > temppoint2.x)
6570 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6574 if (weaponactive != k && weaponstuck != k) {
6575 if (weapons[i].getType() == knife) {
6576 weapons[i].smallrotation = -70;
6577 weapons[i].smallrotation2 = 10;
6579 if (weapons[i].getType() == sword) {
6580 weapons[i].smallrotation = -100;
6581 weapons[i].smallrotation2 = -8;
6583 if (weapons[i].getType() == staff) {
6584 weapons[i].smallrotation = -100;
6585 weapons[i].smallrotation2 = -8;
6588 if (weaponstuck == k) {
6589 if (weaponstuckwhere == 0)
6590 weapons[i].smallrotation = 180;
6592 weapons[i].smallrotation = 0;
6593 weapons[i].smallrotation2 = 10;
6602 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6604 if (animCurrent != animTarget)
6606 if (skeleton.free == 2)
6615 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6618 static float distance;
6619 static float olddistance;
6620 static int intersecting;
6621 static int firstintersecting;
6624 static XYZ start, end;
6625 static float slopethreshold = -.4;
6627 firstintersecting = -1;
6631 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6634 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6635 for (i = 0; i < 4; i++) {
6636 for (j = 0; j < model->TriangleNum; j++) {
6637 if (model->facenormals[j].y <= slopethreshold) {
6639 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)));
6640 if (distance < radius) {
6641 point = *p1 - model->facenormals[j] * distance;
6642 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]]))
6645 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6646 &model->vertex[model->Triangles[j].vertex[1]],
6649 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6650 &model->vertex[model->Triangles[j].vertex[2]],
6653 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6654 &model->vertex[model->Triangles[j].vertex[2]],
6657 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6661 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)) {
6662 p1->y = point.y + radius;
6663 if ((animTarget == jumpdownanim || isFlip())) {
6664 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6667 if (animTarget == jumpupanim) {
6669 animTarget = getIdle();
6676 pause_sound(whooshsound);
6677 OPENAL_SetVolume(channels[whooshsound], 0);
6680 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6683 animTarget = getLanding();
6684 emit_sound_at(landsound, coords, 128.);
6687 envsound[numenvsounds] = coords;
6688 envsoundvol[numenvsounds] = 16;
6689 envsoundlife[numenvsounds] = .4;
6697 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6698 olddistance = distance;
6699 firstintersecting = j;
6704 for (j = 0; j < model->TriangleNum; j++) {
6705 if (model->facenormals[j].y > slopethreshold) {
6708 start.y -= radius / 4;
6709 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6710 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6711 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6712 distance = abs((model->facenormals[j].x * start.x)
6713 + (model->facenormals[j].y * start.y)
6714 + (model->facenormals[j].z * start.z)
6715 - ((model->facenormals[j].x * v0.x)
6716 + (model->facenormals[j].y * v0.y)
6717 + (model->facenormals[j].z * v0.z)));
6718 if (distance < radius * .5) {
6719 point = start - model->facenormals[j] * distance;
6720 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6723 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6725 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6727 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6729 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6730 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6732 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6733 if (findLengthfast(&start) < findLengthfast(&velocity))
6736 *p1 += model->facenormals[j] * (distance - radius * .5);
6739 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6740 olddistance = distance;
6741 firstintersecting = j;
6748 *p = DoRotation(*p, 0, *rotate, 0);
6751 *p1 = DoRotation(*p1, 0, *rotate, 0);
6753 return firstintersecting;
6756 void Person::takeWeapon(int weaponId)
6759 weapons[weaponId].owner = id;
6760 if (num_weapons > 0) {
6761 weaponids[num_weapons] = weaponids[0];
6764 weaponids[0] = weaponId;
6767 void Person::addClothes()
6769 if (numclothes > 0) {
6770 for (int i = 0; i < numclothes; i++) {
6777 bool Person::addClothes(const int& clothesId)
6780 const char* fileName = clothes[clothesId];
6782 GLubyte* array = &skeleton.skinText[0];
6786 bool opened = load_image(fileName, texture);
6791 float tintr = clothestintr[clothesId];
6792 float tintg = clothestintg[clothesId];
6793 float tintb = clothestintb[clothesId];
6795 if (tintr > 1) tintr = 1;
6796 if (tintg > 1) tintg = 1;
6797 if (tintb > 1) tintb = 1;
6799 if (tintr < 0) tintr = 0;
6800 if (tintg < 0) tintg = 0;
6801 if (tintb < 0) tintb = 0;
6803 int bytesPerPixel = texture.bpp / 8;
6807 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6808 if (bytesPerPixel == 3)
6810 else if ((i + 1) % 4 == 0)
6811 alphanum = texture.data[i];
6812 if ((i + 1) % 4 || bytesPerPixel == 3) {
6814 texture.data[i] *= tintr;
6816 texture.data[i] *= tintg;
6818 texture.data[i] *= tintb;
6819 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);