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 int tutoriallevel;
61 extern float smoketex;
62 extern int tutorialstage;
63 extern bool reversaltrain;
64 extern bool canattack;
66 extern float damagedealt;
68 extern float hostiletime;
70 extern int indialogue;
72 extern bool gamestarted;
74 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
87 howactive(typeactive),
89 superruntoggle(false),
90 lastattack(0), lastattack2(0), lastattack3(0),
91 currentoffset(), targetoffset(), offset(),
123 rabbitkickenabled(false),
135 superpermanentdamage(0),
149 bleedx(0), bleedy(0),
153 headyaw(0), headpitch(0),
154 targetheadyaw(0), targetheadpitch(0),
165 normalsupdatedelay(0),
168 forwardkeydown(false),
169 forwardstogglekeydown(false),
174 jumptogglekeydown(false),
175 crouchkeydown(false),
176 crouchtogglekeydown(false),
178 drawtogglekeydown(false),
180 throwtogglekeydown(false),
181 attackkeydown(false),
186 crouchkeydowntime(0),
200 whichdirection(false),
201 whichdirectiondelay(0),
202 avoidsomething(false),
211 lefthandmorphness(0),
212 righthandmorphness(0),
216 targetlefthandmorphness(0),
217 targetrighthandmorphness(0),
218 targetheadmorphness(0),
219 targetchestmorphness(0),
220 targettailmorphness(0),
221 lefthandmorphstart(0), lefthandmorphend(0),
222 righthandmorphstart(0), righthandmorphend(0),
223 headmorphstart(0), headmorphend(0),
224 chestmorphstart(0), chestmorphend(0),
225 tailmorphstart(0), tailmorphend(0),
228 highreversaldelay(0),
231 creature(rabbittype),
278 finalpathfindpoint(0),
279 targetpathfindpoint(0),
280 lastpathfindpoint(0),
281 lastpathfindpoint2(0),
282 lastpathfindpoint3(0),
283 lastpathfindpoint4(0),
299 neckspurtparticledelay(0),
303 rabbitkickragdoll(false),
316 * GameTick/doPlayerCollisions
318 void Person::CheckKick()
321 && (animTarget == rabbitkickanim
323 && victim != this->shared_from_this()
325 && animCurrent == rabbitkickanim)
326 && distsq(&coords, &victim->coords) < 1.2
327 && !victim->skeleton.free))
330 if (animation[victim->animTarget].height != lowheight) {
331 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
332 XYZ relative = velocity;
334 Normalise(&relative);
338 if (tutoriallevel != 1)
339 emit_sound_at(heavyimpactsound, victim->coords);
341 for (int i = 0; i < victim->skeleton.num_joints; i++) {
342 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
345 victim->DoDamage(100 * damagemult / victim->protectionhigh);
351 animTarget = backflipanim;
353 velocity = facing * -10;
357 resume_stream(whooshsound);
359 award_bonus(id, cannon);
360 } else if (victim->isCrouch()) {
361 animTarget = rabbitkickreversedanim;
362 animCurrent = rabbitkickreversedanim;
363 victim->animCurrent = rabbitkickreversalanim;
364 victim->animTarget = rabbitkickreversalanim;
370 victim->oldcoords = victim->coords;
371 coords = victim->coords;
372 victim->targetyaw = targetyaw;
373 victim->victim = this->shared_from_this();
380 * GameTick/doPlayerCollisions - spread fire between players
381 * GameTick/doDebugKeys - press f to ignite
382 * Person::DoStuff - spread fire from lit campfires and bushes
384 void Person::CatchFire()
386 XYZ flatfacing, flatvelocity;
388 for (int i = 0; i < 10; i++) {
389 howmany = abs(Random() % (skeleton.num_joints));
391 flatvelocity = skeleton.joints[howmany].velocity;
392 flatfacing = skeleton.joints[howmany].position * scale + coords;
394 flatvelocity = velocity;
395 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
397 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
402 emit_sound_at(firestartsound, coords);
404 emit_stream_at(stream_firesound, coords);
412 * idle animation for this creature (depending on status)
414 int Person::getIdle()
416 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
418 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
419 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
420 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
421 victim->id < Person::players.size())) {
422 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
423 if (creature == rabbittype)
424 return fightidleanim;
425 if (creature == wolftype)
428 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
429 if (weapons[weaponids[weaponactive]].getType() == knife)
430 return knifefightidleanim;
431 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
432 return swordfightidlebothanim;
433 if (weapons[weaponids[weaponactive]].getType() == sword)
434 return swordfightidleanim;
435 if (weapons[weaponids[weaponactive]].getType() == staff)
436 return swordfightidleanim;
438 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
439 return fightsidestep;
441 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
443 if (howactive == typesitting) return sitanim;
444 if (howactive == typesittingwall) return sitwallanim;
445 if (howactive == typesleeping) return sleepanim;
446 if (howactive == typedead1) return dead1anim;
447 if (howactive == typedead2) return dead2anim;
448 if (howactive == typedead3) return dead3anim;
449 if (howactive == typedead4) return dead4anim;
450 if (creature == rabbittype) return bounceidleanim;
451 if (creature == wolftype) return wolfidle;
456 * crouch animation for this creature
458 int Person::getCrouch()
460 if (creature == rabbittype)
462 if (creature == wolftype)
463 return wolfcrouchanim;
468 * running animation for this creature (can be upright or all fours)
472 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
474 if (creature == wolftype && (!superruntoggle))
477 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
478 return rabbitrunninganim;
479 if (creature == wolftype && (superruntoggle))
480 return wolfrunninganim;
486 int Person::getStop()
488 if (creature == rabbittype)
490 if (creature == wolftype)
497 int Person::getLanding()
499 if (creature == rabbittype)
501 if (creature == wolftype)
508 int Person::getLandhard()
510 if (creature == rabbittype)
512 if (creature == wolftype)
513 return wolflandhardanim;
520 * Person::DoAnimations
523 SolidHitBonus(int playerid)
525 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
526 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
528 award_bonus(playerid, solidhit);
532 * spawns blood effects
534 void Person::DoBlood(float howmuch, int which)
536 // FIXME: should abstract out inputs
537 static int bleedxint, bleedyint;
539 if (bloodtoggle && tutoriallevel != 1) {
540 if (bleeding <= 0 && spurt) {
542 for (int i = 0; i < 3; i++) {
543 // emit blood particles
546 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
547 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
548 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
549 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
552 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
553 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
554 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
555 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
558 if (Random() % 2 == 0) // 50% chance
559 for (int i = 0; i < 3; i++) {
560 if (Random() % 2 != 0) {
561 // emit teeth particles
564 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
565 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
568 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
569 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
573 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
575 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
577 Sprite::setLastSpriteSpecial(3); // sets it to teeth
582 // FIXME: manipulating attributes
583 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
586 if (creature == rabbittype)
587 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) {
588 bleedxint = abs(Random() % 512);
589 bleedyint = abs(Random() % 512);
591 if (creature == wolftype)
592 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) {
593 bleedxint = abs(Random() % 512);
594 bleedyint = abs(Random() % 512);
598 bleedy /= realtexdetail;
599 bleedx /= realtexdetail;
600 direction = abs(Random() % 2) * 2 - 1;
609 * spawns big blood effects and ???
610 * modifies character's skin texture
612 void Person::DoBloodBig(float howmuch, int which)
614 static int bleedxint, bleedyint, i, j;
616 if (howmuch && id == 0)
619 if (tutoriallevel != 1 || id == 0)
620 if (aitype != playercontrolled && howmuch > 0) {
624 if (creature == wolftype) {
625 int i = abs(Random() % 2);
627 whichsound = snarlsound;
629 whichsound = snarl2sound;
631 if (creature == rabbittype) {
632 int i = abs(Random() % 2);
634 whichsound = rabbitpainsound;
635 if (i == 1 && howmuch >= 2)
636 whichsound = rabbitpain1sound;
639 if (whichsound != -1) {
640 emit_sound_at(whichsound, coords);
645 if (id == 0 && howmuch > 0) {
646 // FIXME: manipulating attributes
654 if (bloodtoggle && decals && tutoriallevel != 1) {
655 if (bleeding <= 0 && spurt) {
657 for (int i = 0; i < 3; i++) {
658 // emit blood particles
659 // FIXME: copypaste from above
662 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
663 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
664 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
665 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
668 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
669 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
670 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
671 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
676 // weird texture manipulation code follows.
677 // looks like this is painting blood onto the character's skin texture
678 // FIXME: surely there's a better way
680 int offsetx = 0, offsety = 0;
682 offsety = Random() % 40;
683 offsetx = abs(Random() % 60);
685 if (which == 190 || which == 185) {
686 offsety = Random() % 40;
687 offsetx = abs(Random() % 100) - 20;
690 offsety = Random() % 10;
691 offsetx = Random() % 10;
694 offsety = Random() % 20;
695 offsetx = Random() % 20;
697 if (which == 220 || which == 215) {
707 if (creature == rabbittype)
708 for (i = 0; i < 512; i++) {
709 for (j = 0; j < 512; j++) {
710 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
711 if (i < startx) startx = i;
712 if (j < starty) starty = j;
713 if (i > endx) endx = i;
714 if (j > endy) endy = j;
718 if (creature == wolftype)
719 for (i = 0; i < 512; i++) {
720 for (j = 0; j < 512; j++) {
721 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[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;
735 if (startx < 0) startx = 0;
736 if (starty < 0) starty = 0;
737 if (endx > 512 - 1) endx = 512 - 1;
738 if (endy > 512 - 1) endy = 512 - 1;
739 if (endx < startx) endx = startx;
740 if (endy < starty) endy = starty;
742 startx /= realtexdetail;
743 starty /= realtexdetail;
744 endx /= realtexdetail;
745 endy /= realtexdetail;
747 int texdetailint = realtexdetail;
749 if (creature == rabbittype)
750 for (i = startx; i < endx; i++) {
751 for (j = starty; j < endy; j++) {
752 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) {
753 color = Random() % 85 + 170;
754 where = i * skeleton.skinsize * 3 + j * 3;
755 if (skeleton.skinText[where + 0] > color / 2)
756 skeleton.skinText[where + 0] = color / 2;
757 skeleton.skinText[where + 1] = 0;
758 skeleton.skinText[where + 2] = 0;
762 if (creature == wolftype)
763 for (i = startx; i < endx; i++) {
764 for (j = starty; j < endy; j++) {
765 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) {
766 color = Random() % 85 + 170;
767 where = i * skeleton.skinsize * 3 + j * 3;
768 if (skeleton.skinText[where + 0] > color / 2)
769 skeleton.skinText[where + 0] = color / 2;
770 skeleton.skinText[where + 1] = 0;
771 skeleton.skinText[where + 2] = 0;
775 skeleton.drawmodel.textureptr.bind();
780 if (creature == rabbittype)
781 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) {
782 bleedxint = abs(Random() % 512);
783 bleedyint = abs(Random() % 512);
785 if (creature == wolftype)
786 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) {
787 bleedxint = abs(Random() % 512);
788 bleedyint = abs(Random() % 512);
790 bleedy = bleedxint + offsetx;
791 bleedx = bleedyint + offsety;
792 bleedy /= realtexdetail;
793 bleedx /= realtexdetail;
798 if (bleedx > skeleton.skinsize - 1)
799 bleedx = skeleton.skinsize - 1;
800 if (bleedy > skeleton.skinsize - 1)
801 bleedy = skeleton.skinsize - 1;
802 direction = abs(Random() % 2) * 2 - 1;
805 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
806 deathbleeding += bleeding;
807 bloodloss += bleeding * 3;
809 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
810 if (abs(Random() % 2) == 0) {
811 aitype = gethelptype;
814 aitype = attacktypecutoff;
822 * similar to DoBloodBig
824 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
828 static XYZ startpoint, endpoint, colpoint, movepoint;
829 static float rotationpoint;
831 static XYZ p1, p2, p3, p0;
834 float coordsx, coordsy;
837 if (bloodtoggle && decals && tutoriallevel != 1) {
840 where = DoRotation(where, 0, -yaw, 0);
848 // ray testing for a tri in the character model
849 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
850 if (whichtri != -1) {
851 // low level geometry math
853 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
854 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
855 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
857 bary.x = distsq(&p0, &p1);
858 bary.y = distsq(&p0, &p2);
859 bary.z = distsq(&p0, &p3);
861 total = bary.x + bary.y + bary.z;
870 total = bary.x + bary.y + bary.z;
876 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
877 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
878 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
879 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
880 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
881 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
882 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;
883 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;
885 if (bleeding <= 0 && spurt) {
887 for (int i = 0; i < 3; i++) {
888 // emit blood particles
889 // FIXME: more copypaste code
892 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
893 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
894 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
895 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
898 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
899 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
900 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
901 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
906 // texture manipulation follows
908 int offsetx = 0, offsety = 0;
909 offsetx = (1 + coordsy) * 512 - 291;
910 offsety = coordsx * 512 - 437;
917 if (creature == rabbittype)
918 for (i = 0; i < 512; i++) {
919 for (j = 0; j < 512; j++) {
920 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
921 if (i < startx) startx = i;
922 if (j < starty) starty = j;
923 if (i > endx) endx = i;
924 if (j > endy) endy = j;
928 if (creature == wolftype)
929 for (i = 0; i < 512; i++) {
930 for (j = 0; j < 512; j++) {
931 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[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;
944 if (startx < 0) startx = 0;
945 if (starty < 0) starty = 0;
946 if (endx > 512 - 1) endx = 512 - 1;
947 if (endy > 512 - 1) endy = 512 - 1;
948 if (endx < startx) endx = startx;
949 if (endy < starty) endy = starty;
951 startx /= realtexdetail;
952 starty /= realtexdetail;
953 endx /= realtexdetail;
954 endy /= realtexdetail;
956 int texdetailint = realtexdetail;
958 if (creature == rabbittype)
959 for (i = startx; i < endx; i++) {
960 for (j = starty; j < endy; j++) {
961 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) {
962 color = Random() % 85 + 170;
963 where = i * skeleton.skinsize * 3 + j * 3;
964 if (skeleton.skinText[where + 0] > color / 2)
965 skeleton.skinText[where + 0] = color / 2;
966 skeleton.skinText[where + 1] = 0;
967 skeleton.skinText[where + 2] = 0;
968 } 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) {
969 color = Random() % 85 + 170;
970 where = i * skeleton.skinsize * 3 + j * 3;
971 if (skeleton.skinText[where + 0] > color / 2)
972 skeleton.skinText[where + 0] = color / 2;
973 skeleton.skinText[where + 1] = 0;
974 skeleton.skinText[where + 2] = 0;
978 if (creature == wolftype)
979 for (i = startx; i < endx; i++) {
980 for (j = starty; j < endy; j++) {
981 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) {
982 color = Random() % 85 + 170;
983 where = i * skeleton.skinsize * 3 + j * 3;
984 if (skeleton.skinText[where + 0] > color / 2)
985 skeleton.skinText[where + 0] = color / 2;
986 skeleton.skinText[where + 1] = 0;
987 skeleton.skinText[where + 2] = 0;
988 } 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) {
989 color = Random() % 85 + 170;
990 where = i * skeleton.skinsize * 3 + j * 3;
991 if (skeleton.skinText[where + 0] > color / 2)
992 skeleton.skinText[where + 0] = color / 2;
993 skeleton.skinText[where + 1] = 0;
994 skeleton.skinText[where + 2] = 0;
998 skeleton.drawmodel.textureptr.bind();
1001 bleedy = (1 + coordsy) * 512;
1002 bleedx = coordsx * 512;
1003 bleedy /= realtexdetail;
1004 bleedx /= realtexdetail;
1009 if (bleedx > skeleton.skinsize - 1)
1010 bleedx = skeleton.skinsize - 1;
1011 if (bleedy > skeleton.skinsize - 1)
1012 bleedy = skeleton.skinsize - 1;
1013 direction = abs(Random() % 2) * 2 - 1;
1018 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1019 deathbleeding += bleeding;
1020 bloodloss += bleeding * 3;
1022 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1023 if (abs(Random() % 2) == 0) {
1024 aitype = gethelptype;
1027 aitype = attacktypecutoff;
1038 * guessing this performs a reversal
1040 void Person::Reverse()
1042 if (!((victim->aitype == playercontrolled
1044 || staggerdelay <= 0)
1045 && victim->animTarget != jumpupanim
1046 && victim->animTarget != jumpdownanim
1047 && (tutoriallevel != 1 || cananger)
1051 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1052 && (victim->id != 0 || difficulty >= 2)
1053 && (creature != wolftype || victim->creature == wolftype))
1056 if (animTarget == sweepanim) {
1057 animTarget = sweepreversedanim;
1058 animCurrent = sweepreversedanim;
1059 victim->animCurrent = sweepreversalanim;
1060 victim->animTarget = sweepreversalanim;
1062 if (animTarget == spinkickanim) {
1063 animTarget = spinkickreversedanim;
1064 animCurrent = spinkickreversedanim;
1065 victim->animCurrent = spinkickreversalanim;
1066 victim->animTarget = spinkickreversalanim;
1068 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1069 if (animTarget == rabbittacklinganim) {
1072 victim->frameCurrent = 6;
1073 victim->frameTarget = 7;
1075 animTarget = upunchreversedanim;
1076 animCurrent = upunchreversedanim;
1077 victim->animCurrent = upunchreversalanim;
1078 victim->animTarget = upunchreversalanim;
1080 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1081 if (victim->weaponactive != -1) {
1082 victim->throwtogglekeydown = 1;
1083 XYZ tempVelocity = victim->velocity * .2;
1084 if (tempVelocity.x == 0)
1085 tempVelocity.x = .1;
1086 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1087 victim->num_weapons--;
1088 if (victim->num_weapons) {
1089 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1090 if (victim->weaponstuck == victim->num_weapons)
1091 victim->weaponstuck = 0;
1094 victim->weaponactive = -1;
1095 for (unsigned j = 0; j < Person::players.size(); j++) {
1096 Person::players[j]->wentforweapon = 0;
1100 animTarget = staffhitreversedanim;
1101 animCurrent = staffhitreversedanim;
1102 victim->animCurrent = staffhitreversalanim;
1103 victim->animTarget = staffhitreversalanim;
1105 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1106 if (victim->weaponactive != -1) {
1107 victim->throwtogglekeydown = 1;
1108 XYZ tempVelocity = victim->velocity * .2;
1109 if (tempVelocity.x == 0)
1110 tempVelocity.x = .1;
1111 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1112 victim->num_weapons--;
1113 if (victim->num_weapons) {
1114 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1115 if (victim->weaponstuck == victim->num_weapons)
1116 victim->weaponstuck = 0;
1119 victim->weaponactive = -1;
1120 for (unsigned j = 0; j < Person::players.size(); j++) {
1121 Person::players[j]->wentforweapon = 0;
1124 animTarget = staffspinhitreversedanim;
1125 animCurrent = staffspinhitreversedanim;
1126 victim->animCurrent = staffspinhitreversalanim;
1127 victim->animTarget = staffspinhitreversalanim;
1129 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1130 if (victim->weaponactive != -1) {
1131 victim->throwtogglekeydown = 1;
1132 XYZ tempVelocity = victim->velocity * .2;
1133 if (tempVelocity.x == 0)
1134 tempVelocity.x = .1;
1135 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1136 victim->num_weapons--;
1137 if (victim->num_weapons) {
1138 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1139 if (victim->weaponstuck == victim->num_weapons)
1140 victim->weaponstuck = 0;
1143 victim->weaponactive = -1;
1144 for (unsigned j = 0; j < Person::players.size(); j++) {
1145 Person::players[j]->wentforweapon = 0;
1148 animTarget = swordslashreversedanim;
1149 animCurrent = swordslashreversedanim;
1150 victim->animCurrent = swordslashreversalanim;
1151 victim->animTarget = swordslashreversalanim;
1153 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1154 if (victim->weaponactive != -1) {
1155 victim->throwtogglekeydown = 1;
1156 XYZ tempVelocity = victim->velocity * .2;
1157 if (tempVelocity.x == 0)
1158 tempVelocity.x = .1;
1159 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1160 victim->num_weapons--;
1161 if (victim->num_weapons) {
1162 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1163 if (victim->weaponstuck == victim->num_weapons)
1164 victim->weaponstuck = 0;
1167 victim->weaponactive = -1;
1168 for (unsigned j = 0; j < Person::players.size(); j++) {
1169 Person::players[j]->wentforweapon = 0;
1172 animTarget = knifeslashreversedanim;
1173 animCurrent = knifeslashreversedanim;
1174 victim->animCurrent = knifeslashreversalanim;
1175 victim->animTarget = knifeslashreversalanim;
1177 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1178 victim->targettilt2 = targettilt2;
1179 victim->frameCurrent = frameCurrent;
1180 victim->frameTarget = frameTarget;
1181 victim->target = target;
1182 victim->velocity = 0;
1183 victim->oldcoords = victim->coords;
1184 victim->coords = coords;
1185 victim->targetyaw = targetyaw;
1186 victim->yaw = targetyaw;
1187 victim->victim = this->shared_from_this();
1189 if (animTarget == winduppunchanim) {
1190 animTarget = winduppunchblockedanim;
1191 victim->animTarget = blockhighleftanim;
1192 victim->frameTarget = 1;
1193 victim->target = .5;
1194 victim->victim = this->shared_from_this();
1195 victim->targetyaw = targetyaw + 180;
1197 if (animTarget == wolfslapanim) {
1198 animTarget = winduppunchblockedanim;
1199 victim->animTarget = blockhighleftanim;
1200 victim->frameTarget = 1;
1201 victim->target = .5;
1202 victim->victim = this->shared_from_this();
1203 victim->targetyaw = targetyaw + 180;
1205 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1206 animTarget = swordslashparriedanim;
1207 parriedrecently = .4;
1208 victim->parriedrecently = 0;
1209 victim->animTarget = swordslashparryanim;
1210 victim->frameTarget = 1;
1211 victim->target = .5;
1212 victim->victim = this->shared_from_this();
1213 victim->targetyaw = targetyaw + 180;
1215 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1216 if (victim->weaponactive != -1) {
1217 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1218 if (weapons[victim->weaponids[0]].getType() == staff)
1219 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1220 if (weapons[weaponids[0]].getType() == staff)
1221 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1222 emit_sound_at(swordstaffsound, victim->coords);
1224 emit_sound_at(metalhitsound, victim->coords);
1228 victim->Puff(righthand);
1230 victim->frameTarget = 0;
1231 victim->animTarget = staggerbackhighanim;
1232 victim->targetyaw = targetyaw + 180;
1234 aim = DoRotation(facing, 0, 90, 0) * 21;
1236 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1237 victim->num_weapons--;
1238 if (victim->num_weapons) {
1239 victim->weaponids[0] = victim->weaponids[num_weapons];
1240 if (victim->weaponstuck == victim->num_weapons)
1241 victim->weaponstuck = 0;
1243 victim->weaponactive = -1;
1244 for (unsigned i = 0; i < Person::players.size(); i++) {
1245 Person::players[i]->wentforweapon = 0;
1249 if (abs(Random() % 20) == 0) {
1250 if (weaponactive != -1) {
1251 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1252 if (weapons[victim->weaponids[0]].getType() == staff)
1253 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1254 if (weapons[weaponids[0]].getType() == staff)
1255 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1257 emit_sound_at(swordstaffsound, coords);
1259 emit_sound_at(metalhitsound, coords);
1267 animTarget = staggerbackhighanim;
1268 targetyaw = targetyaw + 180;
1270 aim = DoRotation(facing, 0, 90, 0) * 21;
1272 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1275 weaponids[0] = weaponids[num_weapons];
1276 if (weaponstuck == num_weapons)
1280 for (unsigned i = 0; i < Person::players.size(); i++) {
1281 Person::players[i]->wentforweapon = 0;
1288 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1289 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1290 victim->animTarget = dodgebackanim;
1291 victim->frameTarget = 0;
1295 rotatetarget = coords - victim->coords;
1296 Normalise(&rotatetarget);
1297 victim->targetyaw = -asin(0 - rotatetarget.x);
1298 victim->targetyaw *= 360 / 6.28;
1299 if (rotatetarget.z < 0)
1300 victim->targetyaw = 180 - victim->targetyaw;
1302 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1304 victim->lastattack3 = victim->lastattack2;
1305 victim->lastattack2 = victim->lastattack;
1306 victim->lastattack = victim->animTarget;
1308 victim->animTarget = sweepanim;
1309 victim->frameTarget = 0;
1313 rotatetarget = coords - victim->coords;
1314 Normalise(&rotatetarget);
1315 victim->targetyaw = -asin(0 - rotatetarget.x);
1316 victim->targetyaw *= 360 / 6.28;
1317 if (rotatetarget.z < 0)
1318 victim->targetyaw = 180 - victim->targetyaw;
1320 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1322 victim->lastattack3 = victim->lastattack2;
1323 victim->lastattack2 = victim->lastattack;
1324 victim->lastattack = victim->animTarget;
1329 victim->velocity = 0;
1331 if (aitype != playercontrolled)
1333 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1335 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1337 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1340 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1347 void Person::DoDamage(float howmuch)
1349 // subtract health (temporary?)
1350 if (tutoriallevel != 1)
1351 damage += howmuch / power;
1354 damagedealt += howmuch / power;
1356 damagetaken += howmuch / power;
1359 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1362 if (tutoriallevel != 1)
1363 permanentdamage += howmuch / 2 / power;
1364 if (tutoriallevel != 1)
1365 superpermanentdamage += howmuch / 4 / power;
1367 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1369 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1373 camerashake += howmuch / 100;
1374 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1375 blackout = damage / damagetolerance;
1380 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1381 aitype = attacktypecutoff;
1382 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1383 if (abs(Random() % 2) == 0) {
1384 aitype = gethelptype;
1387 aitype = attacktypecutoff;
1391 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1394 for (int i = 0; i < skeleton.num_joints; i++) {
1395 if (skeleton.free) {
1396 flatvelocity2 = skeleton.joints[i].velocity;
1397 flatfacing2 = skeleton.joints[i].position * scale + coords;
1399 flatvelocity2 = velocity;
1400 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1402 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1403 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1404 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1405 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1406 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1407 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1410 emit_sound_at(splattersound, coords);
1415 if (!dead && creature == wolftype) {
1416 award_bonus(0, Wolfbonus);
1423 if (tutoriallevel != 1 || id == 0)
1424 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1425 int whichsound = -1;
1427 if (creature == wolftype) {
1428 int i = abs(Random() % 2);
1430 whichsound = snarlsound;
1432 whichsound = snarl2sound;
1434 if (creature == rabbittype) {
1435 int i = abs(Random() % 2);
1437 whichsound = rabbitpainsound;
1438 if (i == 1 && damage > damagetolerance)
1439 whichsound = rabbitpain1sound;
1442 if (whichsound != -1) {
1443 emit_sound_at(whichsound, coords);
1444 addEnvSound(coords);
1451 * calculate/animate head facing direction?
1453 void Person::DoHead()
1455 static XYZ rotatearound;
1457 static float lookspeed = 500;
1459 if (!freeze && !winfreeze) {
1462 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1463 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1465 while (targetheadyaw > 180)targetheadyaw -= 360;
1466 while (targetheadyaw < -180)targetheadyaw += 360;
1468 if (targetheadyaw > 160)
1469 targetheadpitch = targetheadpitch * -1;
1470 if (targetheadyaw < -160)
1471 targetheadpitch = targetheadpitch * -1;
1472 if (targetheadyaw > 160)
1473 targetheadyaw = targetheadyaw - 180;
1474 if (targetheadyaw < -160)
1475 targetheadyaw = targetheadyaw + 180;
1477 if (targetheadpitch > 120)
1478 targetheadpitch = 120;
1479 if (targetheadpitch < -120)
1480 targetheadpitch = -120;
1481 if (targetheadyaw > 120)
1482 targetheadyaw = 120;
1483 if (targetheadyaw < -120)
1484 targetheadyaw = -120;
1487 targetheadpitch = 0;
1489 if (targetheadyaw > 80)
1491 if (targetheadyaw < -80)
1492 targetheadyaw = -80;
1493 if (targetheadpitch > 50)
1494 targetheadpitch = 50;
1495 if (targetheadpitch < -50)
1496 targetheadpitch = -50;
1499 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1500 headyaw = targetheadyaw;
1501 else if (headyaw > targetheadyaw) {
1502 headyaw -= multiplier * lookspeed;
1503 } else if (headyaw < targetheadyaw) {
1504 headyaw += multiplier * lookspeed;
1507 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1508 headpitch = targetheadpitch;
1509 else if (headpitch > targetheadpitch) {
1510 headpitch -= multiplier * lookspeed / 2;
1511 } else if (headpitch < targetheadpitch) {
1512 headpitch += multiplier * lookspeed / 2;
1515 rotatearound = jointPos(neck);
1516 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1520 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1521 facing = DoRotation(facing, headpitch * .4, 0, 0);
1522 facing = DoRotation(facing, 0, headyaw * .4, 0);
1525 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1526 facing = DoRotation(facing, headpitch * .8, 0, 0);
1527 facing = DoRotation(facing, 0, headyaw * .8, 0);
1530 if (animTarget == walkanim) {
1531 facing = DoRotation(facing, headpitch * .6, 0, 0);
1532 facing = DoRotation(facing, 0, headyaw * .6, 0);
1535 skeleton.specialforward[0] = facing;
1536 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1537 for (int i = 0; i < skeleton.num_muscles; i++) {
1538 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1539 skeleton.FindRotationMuscle(i, animTarget);
1546 * ragdolls character?
1548 void Person::RagDoll(bool checkcollision)
1553 if (!skeleton.free) {
1556 if (id == 0 && isFlip())
1563 facing = DoRotation(facing, 0, yaw, 0);
1565 skeleton.freetime = 0;
1567 skeleton.longdead = 0;
1570 skeleton.broken = 0;
1571 skeleton.spinny = 1;
1573 skeleton.freefall = 1;
1575 if (!isnormal(velocity.x)) velocity.x = 0;
1576 if (!isnormal(velocity.y)) velocity.y = 0;
1577 if (!isnormal(velocity.z)) velocity.z = 0;
1578 if (!isnormal(yaw)) yaw = 0;
1579 if (!isnormal(coords.x)) coords = 0;
1580 if (!isnormal(tilt)) tilt = 0;
1581 if (!isnormal(tilt2)) tilt2 = 0;
1583 for (int i = 0; i < skeleton.num_joints; i++) {
1584 skeleton.joints[i].delay = 0;
1585 skeleton.joints[i].locked = 0;
1586 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1587 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1588 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1589 skeleton.joints[i].position.y += .1;
1590 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1591 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1594 for (int i = 0; i < skeleton.num_joints; i++) {
1595 skeleton.joints[i].velocity = 0;
1596 skeleton.joints[i].velchange = 0;
1598 skeleton.DoConstraints(&coords, &scale);
1599 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1600 skeleton.DoConstraints(&coords, &scale);
1601 skeleton.DoConstraints(&coords, &scale);
1602 skeleton.DoConstraints(&coords, &scale);
1603 skeleton.DoConstraints(&coords, &scale);
1606 speed = animation[animTarget].speed[frameTarget] * 2;
1607 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1608 speed = animation[animCurrent].speed[frameCurrent] * 2;
1611 speed = transspeed * 2;
1615 for (int i = 0; i < skeleton.num_joints; i++) {
1616 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1617 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);
1619 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1620 change.x = (float)(Random() % 100) / 100;
1621 change.y = (float)(Random() % 100) / 100;
1622 change.z = (float)(Random() % 100) / 100;
1623 skeleton.joints[i].velocity += change;
1624 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1626 change.x = (float)(Random() % 100) / 100;
1627 change.y = (float)(Random() % 100) / 100;
1628 change.z = (float)(Random() % 100) / 100;
1629 skeleton.joints[i].velchange += change;
1630 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1633 if (checkcollision) {
1640 for (j = 0; j < skeleton.num_joints; j++) {
1641 average += skeleton.joints[j].position;
1645 coords += average * scale;
1646 for (j = 0; j < skeleton.num_joints; j++) {
1647 skeleton.joints[j].position -= average;
1650 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1651 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1652 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1653 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1654 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1657 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1658 coords.x = lowpoint.x;
1659 coords.z = lowpoint.z;
1668 for (int i = 0; i < skeleton.num_joints; i++) {
1669 velocity += skeleton.joints[i].velocity * scale;
1671 velocity /= skeleton.num_joints;
1674 if (Random() % 2 == 0) {
1675 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1676 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1677 weapons[weaponids[0]].velocity.x += .01;
1680 weaponids[0] = weaponids[num_weapons];
1681 if (weaponstuck == num_weapons)
1685 for (unsigned i = 0; i < Person::players.size(); i++) {
1686 Person::players[i]->wentforweapon = 0;
1691 animTarget = bounceidleanim;
1692 animCurrent = bounceidleanim;
1702 void Person::FootLand(int which, float opacity)
1704 static XYZ terrainlight;
1705 static XYZ footvel, footpoint;
1706 if (opacity >= 1 || skiddelay <= 0)
1710 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1712 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1713 //footpoint.y=coords.y;
1714 if (distsq(&footpoint, &viewer))
1715 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1716 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1717 footvel = velocity / 5;
1721 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1723 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1724 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1725 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1726 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1727 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1728 if (opacity >= 1 || detail == 2)
1730 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1731 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1732 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1733 footvel = velocity / 5;
1737 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1739 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1740 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1741 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1742 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1743 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1744 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1745 footvel = velocity / 5;
1749 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1751 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1752 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1753 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1754 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1755 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1756 if (opacity >= 1 || detail == 2)
1758 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1759 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1760 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1761 footvel = velocity / 5;
1765 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1767 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1768 //footpoint.y=coords.y;
1769 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1770 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1775 * make a puff effect at a body part (dust effect?)
1777 void Person::Puff(int whichlabel)
1779 static XYZ footvel, footpoint;
1782 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1783 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1787 * I think I added this in an attempt to clean up code
1789 void Person::setAnimation(int animation)
1791 animTarget = animation;
1800 void Person::DoAnimations()
1802 if (!skeleton.free) {
1803 static float oldtarget;
1805 if (isIdle() && animCurrent != getIdle())
1806 normalsupdatedelay = 0;
1808 if (animTarget == tempanim || animCurrent == tempanim) {
1809 animation[tempanim] = tempanimation;
1811 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1817 vel[0] = velocity.x;
1818 vel[1] = velocity.y;
1819 vel[2] = velocity.z;
1822 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1823 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1825 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1827 if (!crouchkeydown && velocity.y >= -15)
1830 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1835 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1837 if (normaldotproduct(targfacing, velocity) >= -.3)
1838 animTarget = flipanim;
1840 animTarget = backflipanim;
1841 crouchtogglekeydown = 1;
1849 if (animation[animTarget].attack != reversed)
1851 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1852 crouchtogglekeydown = 0;
1853 if (aitype == playercontrolled)
1856 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1859 crouchtogglekeydown = 1;
1863 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1865 normalsupdatedelay = 0;
1869 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1871 emit_sound_at(fireendsound, coords);
1872 pause_sound(stream_firesound);
1876 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1877 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1879 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1880 if (normaldotproduct(victim->facing, facing) > 0)
1881 victim->animTarget = rabbittackledbackanim;
1883 victim->animTarget = rabbittackledfrontanim;
1884 victim->frameTarget = 2;
1887 victim->targetyaw = yaw;
1888 if (victim->aitype == gethelptype)
1889 victim->DoDamage(victim->damagetolerance - victim->damage);
1890 //victim->DoDamage(30);
1891 if (creature == wolftype) {
1893 emit_sound_at(clawslicesound, victim->coords);
1895 victim->DoBloodBig(1 / victim->armorhead, 210);
1897 award_bonus(id, TackleBonus,
1898 victim->aitype == gethelptype ? 50 : 0);
1902 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1903 if (weapons[weaponids[0]].getType() == knife) {
1904 if (weaponactive == -1)
1906 else if (weaponactive == 0)
1909 if (weaponactive == -1) {
1910 emit_sound_at(knifesheathesound, coords);
1912 if (weaponactive != -1) {
1913 emit_sound_at(knifedrawsound, coords, 128);
1916 drawtogglekeydown = 1;
1919 if (tutoriallevel != 1 || id == 0)
1920 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1923 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1924 if (animation[animTarget].label[frameTarget] == 1)
1925 whichsound = footstepsound;
1927 whichsound = footstepsound2;
1928 if (animation[animTarget].label[frameTarget] == 1)
1930 if (animation[animTarget].label[frameTarget] == 2)
1932 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1938 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1939 if (animation[animTarget].label[frameTarget] == 1)
1940 whichsound = footstepsound3;
1942 whichsound = footstepsound4;
1946 if (animation[animTarget].label[frameTarget] == 1)
1947 whichsound = footstepsound3;
1949 whichsound = footstepsound4;
1951 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1952 if (animation[animTarget].attack != neutral) {
1953 unsigned r = abs(Random() % 3);
1955 whichsound = lowwhooshsound;
1957 whichsound = midwhooshsound;
1959 whichsound = highwhooshsound;
1961 if (animation[animTarget].attack == neutral)
1962 whichsound = movewhooshsound;
1963 } else if (animation[animTarget].label[frameTarget] == 4)
1964 whichsound = knifeswishsound;
1965 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1966 whichsound = landsound2;
1968 emit_sound_at(whichsound, coords, 256.);
1971 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1972 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
1973 addEnvSound(coords, 15);
1975 addEnvSound(coords, 6);
1979 if (animation[animTarget].label[frameTarget] == 3) {
1981 emit_sound_at(whichsound, coords, 128.);
1986 if (tutoriallevel != 1 || id == 0)
1987 if (speechdelay <= 0)
1988 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1989 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1990 int whichsound = -1;
1991 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1992 if (animation[animTarget].attack != neutral) {
1993 unsigned r = abs(Random() % 4);
1994 if (creature == rabbittype) {
1995 if (r == 0) whichsound = rabbitattacksound;
1996 if (r == 1) whichsound = rabbitattack2sound;
1997 if (r == 2) whichsound = rabbitattack3sound;
1998 if (r == 3) whichsound = rabbitattack4sound;
2000 if (creature == wolftype) {
2001 if (r == 0) whichsound = barksound;
2002 if (r == 1) whichsound = bark2sound;
2003 if (r == 2) whichsound = bark3sound;
2004 if (r == 3) whichsound = barkgrowlsound;
2010 if (whichsound != -1) {
2011 emit_sound_at(whichsound, coords);
2017 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2023 currentoffset = targetoffset;
2024 frameTarget = frameCurrent;
2025 animCurrent = animTarget;
2028 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2029 for (unsigned i = 0; i < weapons.size(); i++) {
2030 if (weapons[i].owner == -1)
2031 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2032 if (distsq(&coords, &weapons[i].position) >= 1) {
2033 if (weapons[i].getType() != staff) {
2034 emit_sound_at(knifedrawsound, coords, 128.);
2043 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2044 for (unsigned i = 0; i < weapons.size(); i++) {
2045 bool willwork = true;
2046 if (weapons[i].owner != -1)
2047 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2048 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2049 if (Person::players[weapons[i].owner]->num_weapons > 1)
2051 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2052 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2053 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2054 bool fleshstuck = false;
2055 if (weapons[i].owner != -1)
2056 if (victim->weaponstuck != -1) {
2057 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2062 emit_sound_at(fleshstabremovesound, coords, 128.);
2064 if (weapons[i].getType() != staff) {
2065 emit_sound_at(knifedrawsound, coords, 128.);
2068 if (weapons[i].owner != -1) {
2069 victim = Person::players[weapons[i].owner];
2070 if (victim->num_weapons == 1)
2071 victim->num_weapons = 0;
2073 victim->num_weapons = 1;
2075 //victim->weaponactive=-1;
2076 victim->skeleton.longdead = 0;
2077 victim->skeleton.free = 1;
2078 victim->skeleton.broken = 0;
2080 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2081 victim->skeleton.joints[j].velchange = 0;
2082 victim->skeleton.joints[j].locked = 0;
2088 Normalise(&relative);
2089 XYZ footvel, footpoint;
2091 footpoint = weapons[i].position;
2092 if (victim->weaponstuck != -1) {
2093 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2095 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2096 weapons[i].bloody = 2;
2097 weapons[i].blooddrip = 5;
2098 victim->weaponstuck = -1;
2101 if (victim->num_weapons > 0) {
2102 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2103 victim->weaponstuck = 0;
2104 if (victim->weaponids[0] == int(i))
2105 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2108 victim->jointVel(abdomen) += relative * 6;
2109 victim->jointVel(neck) += relative * 6;
2110 victim->jointVel(rightshoulder) += relative * 6;
2111 victim->jointVel(leftshoulder) += relative * 6;
2119 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2120 if (weaponactive == -1)
2122 else if (weaponactive == 0) {
2124 if (num_weapons == 2) {
2126 buffer = weaponids[0];
2127 weaponids[0] = weaponids[1];
2128 weaponids[1] = buffer;
2131 if (weaponactive == -1) {
2132 emit_sound_at(knifesheathesound, coords, 128.);
2134 if (weaponactive != -1) {
2135 emit_sound_at(knifedrawsound, coords, 128.);
2140 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2141 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2142 Normalise(&rotatetarget);
2143 targetyaw = -asin(0 - rotatetarget.x);
2144 targetyaw *= 360 / 6.28;
2145 if (rotatetarget.z < 0)
2146 targetyaw = 180 - targetyaw;
2148 if (animTarget == walljumprightkickanim)
2150 if (animTarget == walljumpleftkickanim)
2156 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2159 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2164 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2165 animTarget = rabbittackleanim;
2167 emit_sound_at(jumpsound, coords);
2175 targetloc = velocity;
2176 Normalise(&targetloc);
2177 targetloc += coords;
2178 for (unsigned i = 0; i < Person::players.size(); i++) {
2180 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2181 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2185 if (closestid != -1)
2186 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2188 victim = Person::players[closestid];
2189 coords = victim->coords;
2190 animCurrent = rabbittacklinganim;
2191 animTarget = rabbittacklinganim;
2195 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2196 rotatetarget = coords - victim->coords;
2197 Normalise(&rotatetarget);
2198 targetyaw = -asin(0 - rotatetarget.x);
2199 targetyaw *= 360 / 6.28;
2200 if (rotatetarget.z < 0)
2201 targetyaw = 180 - targetyaw;
2203 if (animTarget != rabbitrunninganim) {
2204 emit_sound_at(jumpsound, coords, 128.);
2210 float damagemult = 1 * power;
2211 if (creature == wolftype)
2212 damagemult = 2.5 * power;
2214 damagemult /= victim->damagetolerance / 200;
2216 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2217 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2218 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2222 if (Random() % 2 || creature == wolftype) {
2225 if (creature == wolftype)
2228 if (tutoriallevel != 1) {
2229 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2231 if (creature == wolftype) {
2232 emit_sound_at(clawslicesound, victim->coords, 128.);
2234 victim->DoBloodBig(2 / victim->armorhead, 175);
2238 relative = victim->coords - coords;
2240 Normalise(&relative);
2241 relative = DoRotation(relative, 0, -90, 0);
2242 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2243 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2245 victim->jointVel(head) += relative * damagemult * 200;
2248 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2254 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2255 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2259 if (Random() % 2 || creature == wolftype) {
2261 if (creature == wolftype)
2264 emit_sound_at(whooshhitsound, victim->coords);
2265 if (creature == wolftype) {
2266 emit_sound_at(clawslicesound, victim->coords, 128.);
2268 victim->DoBloodBig(2, 175);
2272 relative = victim->coords - coords;
2274 Normalise(&relative);
2276 Normalise(&relative);
2277 relative = DoRotation(relative, 0, 90, 0);
2278 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2279 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2281 victim->jointVel(head) += relative * damagemult * 100;
2284 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2288 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2289 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2295 if (tutoriallevel != 1) {
2296 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2298 if (creature == wolftype) {
2299 emit_sound_at(clawslicesound, victim->coords, 128.);
2301 victim->DoBloodBig(2 / victim->armorhead, 175);
2307 Normalise(&relative);
2308 relative = DoRotation(relative, 0, -90, 0);
2309 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2310 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2312 victim->jointVel(head) += relative * damagemult * 200;
2315 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2317 if (victim->damage > victim->damagetolerance)
2318 award_bonus(id, style);
2324 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2325 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2331 if (tutoriallevel != 1) {
2332 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2334 if (creature == wolftype) {
2335 emit_sound_at(clawslicesound, victim->coords, 128.);
2337 victim->DoBloodBig(2 / victim->armorhead, 175);
2343 Normalise(&relative);
2344 relative = DoRotation(relative, 0, 90, 0);
2345 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2346 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2348 victim->jointVel(head) += relative * damagemult * 200;
2351 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2353 if (victim->damage > victim->damagetolerance)
2354 award_bonus(id, style);
2360 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2361 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2369 emit_sound_at(whooshhitsound, victim->coords);
2372 relative = victim->coords - coords;
2374 Normalise(&relative);
2375 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2376 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2378 victim->jointVel(head) += relative * damagemult * 100;
2381 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2385 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2386 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2390 emit_sound_at(whooshhitsound, victim->coords, 128.);
2392 victim->skeleton.longdead = 0;
2393 victim->skeleton.free = 1;
2394 victim->skeleton.broken = 0;
2395 victim->skeleton.spinny = 1;
2397 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2398 victim->skeleton.joints[i].velchange = 0;
2399 victim->skeleton.joints[i].delay = 0;
2400 victim->skeleton.joints[i].locked = 0;
2401 //victim->skeleton.joints[i].velocity=0;
2407 Normalise(&relative);
2408 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2409 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2410 victim->skeleton.joints[i].position.y += relative.y * .3;
2411 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2412 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2414 victim->Puff(abdomen);
2415 victim->jointVel(abdomen).y = relative.y * 400;
2419 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2420 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2424 if (tutoriallevel != 1) {
2425 emit_sound_at(heavyimpactsound, coords, 128.);
2428 relative = victim->coords - coords;
2430 Normalise(&relative);
2431 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2432 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2434 victim->Puff(abdomen);
2435 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2439 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2440 victim->jointVel(abdomen) += relative * damagemult * 300;
2444 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2445 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2449 if (tutoriallevel != 1) {
2450 emit_sound_at(thudsound, coords);
2453 victim->skeleton.longdead = 0;
2454 victim->skeleton.free = 1;
2455 victim->skeleton.broken = 0;
2456 victim->skeleton.spinny = 1;
2458 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2459 victim->skeleton.joints[i].velchange = 0;
2460 //victim->skeleton.joints[i].delay=0;
2461 victim->skeleton.joints[i].locked = 0;
2464 relative = victim->coords - coords;
2465 Normalise(&relative);
2467 Normalise(&relative);
2468 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2469 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2474 victim->Puff(abdomen);
2475 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2476 victim->jointVel(abdomen) += relative * damagemult * 200;
2485 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2488 if (!victim->skeleton.free)
2492 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2493 emit_sound_at(knifesheathesound, coords, 128.);
2496 if (victim && hasvictim) {
2497 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2499 XYZ where, startpoint, endpoint, movepoint, colpoint;
2500 float rotationpoint;
2502 if (weapons[weaponids[weaponactive]].getType() == knife) {
2503 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2504 where -= victim->coords;
2505 if (!victim->skeleton.free)
2506 where = DoRotation(where, 0, -victim->yaw, 0);
2509 startpoint.y += 100;
2513 if (weapons[weaponids[weaponactive]].getType() == sword) {
2514 where = weapons[weaponids[weaponactive]].position;
2515 where -= victim->coords;
2516 if (!victim->skeleton.free)
2517 where = DoRotation(where, 0, -victim->yaw, 0);
2519 where = weapons[weaponids[weaponactive]].tippoint;
2520 where -= victim->coords;
2521 if (!victim->skeleton.free)
2522 where = DoRotation(where, 0, -victim->yaw, 0);
2525 if (weapons[weaponids[weaponactive]].getType() == staff) {
2526 where = weapons[weaponids[weaponactive]].position;
2527 where -= victim->coords;
2528 if (!victim->skeleton.free)
2529 where = DoRotation(where, 0, -victim->yaw, 0);
2531 where = weapons[weaponids[weaponactive]].tippoint;
2532 where -= victim->coords;
2533 if (!victim->skeleton.free)
2534 where = DoRotation(where, 0, -victim->yaw, 0);
2539 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2541 if (whichtri != -1) {
2542 if (victim->dead != 2) {
2543 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2545 award_bonus(id, FinishedBonus);
2548 weapons[weaponids[weaponactive]].bloody = 2;
2550 victim->skeleton.longdead = 0;
2551 victim->skeleton.free = 1;
2552 victim->skeleton.broken = 0;
2554 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2555 victim->skeleton.joints[i].velchange = 0;
2556 victim->skeleton.joints[i].locked = 0;
2557 //victim->skeleton.joints[i].velocity=0;
2559 emit_sound_at(fleshstabsound, coords, 128);
2562 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2563 weapons[weaponids[weaponactive]].blooddrip += 5;
2564 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2566 if (whichtri == -1) {
2568 emit_sound_at(knifesheathesound, coords, 128.);
2574 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2576 emit_sound_at(knifedrawsound, coords, 128);
2579 if (victim && hasvictim) {
2580 XYZ footvel, footpoint;
2582 emit_sound_at(fleshstabremovesound, coords, 128.);
2585 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2587 if (weapons[weaponids[weaponactive]].getType() == sword) {
2588 XYZ where, startpoint, endpoint, movepoint;
2589 float rotationpoint;
2592 where = weapons[weaponids[weaponactive]].position;
2593 where -= victim->coords;
2594 if (!victim->skeleton.free)
2595 where = DoRotation(where, 0, -victim->yaw, 0);
2597 where = weapons[weaponids[weaponactive]].tippoint;
2598 where -= victim->coords;
2599 if (!victim->skeleton.free)
2600 where = DoRotation(where, 0, -victim->yaw, 0);
2605 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2606 footpoint += victim->coords;
2608 if (whichtri == -1) {
2609 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2612 if (weapons[weaponids[weaponactive]].getType() == staff) {
2613 XYZ where, startpoint, endpoint, movepoint;
2614 float rotationpoint;
2617 where = weapons[weaponids[weaponactive]].position;
2618 where -= victim->coords;
2619 if (!victim->skeleton.free)
2620 where = DoRotation(where, 0, -victim->yaw, 0);
2622 where = weapons[weaponids[weaponactive]].tippoint;
2623 where -= victim->coords;
2624 if (!victim->skeleton.free)
2625 where = DoRotation(where, 0, -victim->yaw, 0);
2630 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2631 footpoint += victim->coords;
2633 if (whichtri == -1) {
2634 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2637 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2639 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2640 victim->skeleton.longdead = 0;
2641 victim->skeleton.free = 1;
2642 victim->skeleton.broken = 0;
2644 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2645 victim->skeleton.joints[i].velchange = 0;
2646 victim->skeleton.joints[i].locked = 0;
2647 //victim->skeleton.joints[i].velocity=0;
2653 Normalise(&relative);
2654 //victim->Puff(abdomen);
2656 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2658 if (victim->bloodloss < victim->damagetolerance) {
2659 victim->bloodloss += 1000;
2663 victim->jointVel(abdomen) += relative * damagemult * 20;
2667 if (!hasvictim && onterrain) {
2668 weapons[weaponids[weaponactive]].bloody = 0;
2669 weapons[weaponids[weaponactive]].blooddrip = 0;
2673 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2674 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2682 if (tutoriallevel != 1) {
2683 emit_sound_at(heavyimpactsound, victim->coords, 128);
2688 relative = victim->coords - coords;
2690 Normalise(&relative);
2691 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2692 victim->skeleton.joints[i].velocity = relative * 30;
2694 victim->jointVel(head) += relative * damagemult * 150;
2696 victim->frameTarget = 0;
2697 victim->animTarget = staggerbackhardanim;
2698 victim->targetyaw = targetyaw + 180;
2700 victim->stunned = 1;
2703 victim->Puff(abdomen);
2704 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2711 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2712 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2716 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2717 if (tutoriallevel != 1) {
2718 emit_sound_at(thudsound, victim->coords);
2720 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2721 if (tutoriallevel != 1) {
2722 emit_sound_at(whooshhitsound, victim->coords);
2725 if (tutoriallevel != 1) {
2726 emit_sound_at(heavyimpactsound, victim->coords);
2730 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2733 relative = victim->coords - coords;
2735 Normalise(&relative);
2737 Normalise(&relative);
2738 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2739 victim->skeleton.joints[i].velocity = relative * 5;
2741 victim->jointVel(abdomen) += relative * damagemult * 400;
2743 victim->frameTarget = 0;
2744 victim->animTarget = staggerbackhardanim;
2745 victim->targetyaw = targetyaw + 180;
2747 victim->stunned = 1;
2749 victim->Puff(abdomen);
2750 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2756 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2757 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2758 if (victim->id == 0)
2760 emit_sound_at(landsound2, victim->coords);
2766 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2767 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2768 if (victim->id == 0)
2771 if (weaponactive != -1) {
2772 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2773 if (weapons[victim->weaponids[0]].getType() == staff)
2774 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2775 if (weapons[weaponids[0]].getType() == staff)
2776 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2778 emit_sound_at(swordstaffsound, victim->coords);
2780 emit_sound_at(metalhitsound, victim->coords);
2788 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2789 if (weaponactive != -1) {
2792 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);
2794 weapons[weaponids[0]].thrown(aim * 50);
2797 weaponids[0] = weaponids[num_weapons];
2803 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2805 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2807 if (tutoriallevel != 1)
2808 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2810 award_bonus(id, Slicebonus);
2811 if (tutoriallevel != 1) {
2812 emit_sound_at(knifeslicesound, victim->coords);
2814 //victim->jointVel(abdomen)+=relative*damagemult*200;
2815 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2816 if (victim->id != 0 || difficulty == 2) {
2817 victim->frameTarget = 0;
2818 victim->animTarget = staggerbackhardanim;
2819 victim->targetyaw = targetyaw + 180;
2823 victim->lowreversaldelay = 0;
2824 victim->highreversaldelay = 0;
2825 if (aitype != playercontrolled)
2826 weaponmissdelay = .6;
2828 if (tutoriallevel != 1)
2829 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2830 weapons[weaponids[weaponactive]].bloody = 1;
2831 if (tutoriallevel != 1)
2832 weapons[weaponids[weaponactive]].blooddrip += 3;
2834 XYZ footvel, footpoint;
2836 if (skeleton.free) {
2837 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2839 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2841 if (tutoriallevel != 1) {
2843 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2844 footvel = DoRotation(facing, 0, 90, 0) * .8;
2846 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2847 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2848 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2849 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2851 if (tutoriallevel == 1) {
2852 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2854 victim->DoDamage(damagemult * 0);
2857 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2858 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2859 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2860 award_bonus(id, Slashbonus);
2862 if (tutoriallevel != 1) {
2863 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2864 victim->DoBloodBig(2 / victim->armorhigh, 190);
2866 victim->DoBloodBig(2 / victim->armorhigh, 185);
2867 victim->deathbleeding = 1;
2868 emit_sound_at(swordslicesound, victim->coords);
2870 //victim->jointVel(abdomen)+=relative*damagemult*200;
2871 if (tutoriallevel != 1) {
2872 victim->frameTarget = 0;
2873 victim->animTarget = staggerbackhardanim;
2874 victim->targetyaw = targetyaw + 180;
2878 if (tutoriallevel != 1) {
2879 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2880 weapons[weaponids[weaponactive]].bloody = 1;
2881 weapons[weaponids[weaponactive]].blooddrip += 3;
2883 float bloodlossamount;
2884 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2885 victim->bloodloss += bloodlossamount / victim->armorhigh;
2886 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2887 victim->DoDamage(damagemult * 0);
2889 XYZ footvel, footpoint;
2891 if (skeleton.free) {
2892 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2894 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2897 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2898 footvel = DoRotation(facing, 0, 90, 0) * .8;
2900 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2901 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2902 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2903 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2906 if (victim->weaponactive != -1) {
2907 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2908 if (weapons[victim->weaponids[0]].getType() == staff)
2909 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2910 if (weapons[weaponids[0]].getType() == staff)
2911 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2913 emit_sound_at(swordstaffsound, victim->coords);
2915 emit_sound_at(metalhitsound, victim->coords);
2921 victim->Puff(righthand);
2923 victim->frameTarget = 0;
2924 victim->animTarget = staggerbackhighanim;
2925 victim->targetyaw = targetyaw + 180;
2927 aim = DoRotation(facing, 0, 90, 0) * 21;
2929 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2930 victim->num_weapons--;
2931 if (victim->num_weapons) {
2932 victim->weaponids[0] = victim->weaponids[num_weapons];
2933 if (victim->weaponstuck == victim->num_weapons)
2934 victim->weaponstuck = 0;
2936 victim->weaponactive = -1;
2937 for (unsigned i = 0; i < Person::players.size(); i++) {
2938 Person::players[i]->wentforweapon = 0;
2945 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2946 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2947 if (tutoriallevel != 1) {
2948 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2952 if (Random() % 2 || creature == wolftype) {
2955 emit_sound_at(staffheadsound, victim->coords);
2959 relative = victim->coords - coords;
2961 Normalise(&relative);
2962 relative = DoRotation(relative, 0, 90, 0);
2964 Normalise(&relative);
2965 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2966 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2968 victim->jointVel(head) += relative * damagemult * 230;
2969 victim->jointVel(neck) += relative * damagemult * 230;
2972 if (tutoriallevel != 1) {
2973 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2975 award_bonus(id, solidhit, 30);
2980 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2981 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2982 if (tutoriallevel != 1) {
2983 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2987 if (Random() % 2 || creature == wolftype) {
2990 emit_sound_at(staffheadsound, victim->coords);
2994 relative = victim->coords - coords;
2996 Normalise(&relative);
2997 relative = DoRotation(relative, 0, -90, 0);
2998 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2999 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3001 victim->jointVel(head) += relative * damagemult * 220;
3002 victim->jointVel(neck) += relative * damagemult * 220;
3005 if (tutoriallevel != 1) {
3006 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3008 award_bonus(id, solidhit, 60);
3013 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3014 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3016 if (tutoriallevel != 1) {
3018 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3021 if (Random() % 2 || creature == wolftype) {
3024 emit_sound_at(staffbodysound, victim->coords);
3026 victim->skeleton.longdead = 0;
3027 victim->skeleton.free = 1;
3028 victim->skeleton.broken = 0;
3030 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3031 victim->skeleton.joints[i].velchange = 0;
3032 victim->skeleton.joints[i].locked = 0;
3033 //victim->skeleton.joints[i].velocity=0;
3039 /*relative=victim->coords-coords;
3041 Normalise(&relative);
3042 relative=DoRotation(relative,0,90,0);*/
3044 Normalise(&relative);
3045 if (!victim->dead) {
3046 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3047 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3050 victim->jointVel(abdomen) += relative * damagemult * 40;
3053 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3054 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3057 //victim->jointVel(abdomen)+=relative*damagemult*20;
3059 victim->Puff(abdomen);
3060 if (tutoriallevel != 1) {
3061 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3063 if (!victim->dead) {
3064 award_bonus(id, solidhit, 40);
3070 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3071 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3076 relative = victim->coords - coords;
3078 Normalise(&relative);
3082 if (animation[victim->animTarget].height == lowheight) {
3088 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3089 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3091 victim->jointVel(head) += relative * damagemult * 200;
3092 if (tutoriallevel != 1) {
3093 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3096 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3097 if (victim->howactive == typesleeping)
3098 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3099 if (creature == wolftype) {
3100 emit_sound_at(clawslicesound, victim->coords, 128.);
3102 victim->DoBloodBig(2 / victim->armorhead, 175);
3105 if (victim->damage >= victim->damagetolerance)
3107 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3108 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3110 victim->jointVel(abdomen) += relative * damagemult * 200;
3111 victim->frameTarget = 0;
3112 victim->animTarget = staggerbackhighanim;
3113 victim->targetyaw = targetyaw + 180;
3115 if (tutoriallevel != 1) {
3116 emit_sound_at(landsound2, victim->coords, 128.);
3118 victim->Puff(abdomen);
3119 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3120 if (creature == wolftype) {
3121 emit_sound_at(clawslicesound, victim->coords, 128.);
3123 victim->DoBloodBig(2 / victim->armorhigh, 170);
3130 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3131 if ((victim->animTarget != jumpupanim) &&
3132 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3133 (victim != this->shared_from_this())) {
3137 if (tutoriallevel != 1) {
3138 emit_sound_at(landsound2, victim->coords, 128.);
3141 relative = victim->coords - coords;
3143 Normalise(&relative);
3145 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3148 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3149 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3151 relative = DoRotation(relative, 0, -90, 0);
3153 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3154 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)
3155 victim->skeleton.joints[i].velocity = relative * 80;
3157 victim->Puff(rightankle);
3158 victim->Puff(leftankle);
3159 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3161 if (victim->damage >= victim->damagetolerance)
3163 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3164 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3166 relative = DoRotation(relative, 0, -90, 0);
3167 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3168 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)
3169 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3171 victim->jointVel(abdomen) += relative * damagemult * 200;
3172 victim->frameTarget = 0;
3173 victim->animTarget = staggerbackhighanim;
3174 victim->targetyaw = targetyaw + 180;
3176 if (tutoriallevel != 1) {
3177 emit_sound_at(landsound2, victim->coords, 128.);
3179 victim->Puff(abdomen);
3180 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3188 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3189 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3197 if (tutoriallevel != 1) {
3198 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3200 if (creature == wolftype) {
3201 emit_sound_at(clawslicesound, victim->coords, 128);
3203 victim->DoBloodBig(2 / victim->armorhigh, 170);
3207 relative = victim->coords - oldcoords;
3209 Normalise(&relative);
3210 //relative=DoRotation(relative,0,-90,0);
3211 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3212 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3214 victim->jointVel(abdomen) += relative * damagemult * 200;
3216 victim->Puff(abdomen);
3217 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3219 award_bonus(id, Reversal);
3222 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3223 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3224 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3225 takeWeapon(victim->weaponids[victim->weaponactive]);
3226 victim->num_weapons--;
3227 if (victim->num_weapons > 0) {
3228 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3230 victim->weaponactive = -1;
3235 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3243 emit_sound_at(whooshhitsound, victim->coords, 128.);
3246 relative = victim->coords - oldcoords;
3248 Normalise(&relative);
3249 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3250 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3252 victim->jointVel(abdomen) += relative * damagemult * 200;
3254 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3257 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3266 award_bonus(id, staffreversebonus);
3268 if (tutoriallevel != 1) {
3269 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3272 award_bonus(id, staffreversebonus); // Huh, again?
3275 relative = victim->coords - oldcoords;
3277 Normalise(&relative);
3278 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3279 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3281 victim->jointVel(abdomen) += relative * damagemult * 200;
3283 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3286 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3292 Normalise(&relative);
3294 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3295 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3297 victim->jointVel(lefthand) *= .1;
3298 victim->jointVel(leftwrist) *= .2;
3299 victim->jointVel(leftelbow) *= .5;
3300 victim->jointVel(leftshoulder) *= .7;
3301 victim->jointVel(righthand) *= .1;
3302 victim->jointVel(rightwrist) *= .2;
3303 victim->jointVel(rightelbow) *= .5;
3304 victim->jointVel(rightshoulder) *= .7;
3306 victim->Puff(abdomen);
3307 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3309 award_bonus(id, Reversal);
3313 if (weaponactive != -1 || creature == wolftype)
3315 if (creature == rabbittype && weaponactive != -1)
3316 if (weapons[weaponids[0]].getType() == staff)
3319 if (weaponactive != -1) {
3320 victim->DoBloodBig(2 / victim->armorhigh, 225);
3321 emit_sound_at(knifeslicesound, victim->coords);
3322 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3323 weapons[weaponids[weaponactive]].bloody = 1;
3324 weapons[weaponids[weaponactive]].blooddrip += 3;
3326 if (weaponactive == -1 && creature == wolftype) {
3328 emit_sound_at(clawslicesound, victim->coords, 128.);
3330 victim->DoBloodBig(2 / victim->armorhigh, 175);
3337 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3343 Normalise(&relative);
3345 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3346 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3348 victim->jointVel(lefthand) *= .1 - 1;
3349 victim->jointVel(leftwrist) *= .2 - 1;
3350 victim->jointVel(leftelbow) *= .5 - 1;
3351 victim->jointVel(leftshoulder) *= .7 - 1;
3352 victim->jointVel(righthand) *= .1 - 1;
3353 victim->jointVel(rightwrist) *= .2 - 1;
3354 victim->jointVel(rightelbow) *= .5 - 1;
3355 victim->jointVel(rightshoulder) *= .7 - 1;
3357 award_bonus(id, swordreversebonus);
3360 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3368 if (tutoriallevel != 1) {
3369 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3373 relative = victim->coords - oldcoords;
3375 Normalise(&relative);
3376 relative = DoRotation(relative, 0, -90, 0);
3377 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3378 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3380 victim->jointVel(abdomen) += relative * damagemult * 200;
3381 victim->Puff(abdomen);
3382 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3384 award_bonus(id, Reversal);
3387 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3390 victim->skeleton.spinny = 0;
3392 relative = facing * -1;
3394 Normalise(&relative);
3395 if (victim->id == 0)
3397 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3398 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3400 victim->damage = victim->damagetolerance;
3401 victim->permanentdamage = victim->damagetolerance - 1;
3404 if (weaponactive != -1 || creature == wolftype)
3406 if (creature == rabbittype && weaponactive != -1)
3407 if (weapons[weaponids[0]].getType() == staff)
3410 if (weaponactive != -1) {
3411 victim->DoBloodBig(200, 225);
3412 emit_sound_at(knifeslicesound, victim->coords);
3414 weapons[weaponids[weaponactive]].bloody = 2;
3415 weapons[weaponids[weaponactive]].blooddrip += 5;
3418 if (creature == wolftype && weaponactive == -1) {
3419 emit_sound_at(clawslicesound, victim->coords, 128.);
3421 victim->DoBloodBig(2, 175);
3424 award_bonus(id, spinecrusher);
3427 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3428 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3430 if (animTarget == knifefollowanim)
3431 victim->DoBloodBig(200, 210);
3432 if (animTarget == knifesneakattackanim) {
3433 XYZ footvel, footpoint;
3435 footpoint = weapons[weaponids[0]].tippoint;
3437 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3438 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3439 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3440 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3441 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3442 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3443 victim->DoBloodBig(200, 195);
3444 award_bonus(id, tracheotomy);
3446 if (animTarget == knifefollowanim) {
3447 award_bonus(id, Stabbonus);
3448 XYZ footvel, footpoint;
3450 footpoint = weapons[weaponids[0]].tippoint;
3452 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3453 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3454 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3455 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3456 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3457 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3460 victim->bloodloss += 10000;
3461 victim->velocity = 0;
3462 emit_sound_at(fleshstabsound, victim->coords);
3464 weapons[weaponids[weaponactive]].bloody = 2;
3465 weapons[weaponids[weaponactive]].blooddrip += 5;
3469 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3471 victim->velocity = 0;
3472 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3473 victim->skeleton.joints[i].velocity = 0;
3475 if (animTarget == knifefollowanim) {
3477 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3478 victim->skeleton.joints[i].velocity = 0;
3481 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3482 emit_sound_at(fleshstabremovesound, victim->coords);
3484 weapons[weaponids[weaponactive]].bloody = 2;
3485 weapons[weaponids[weaponactive]].blooddrip += 5;
3487 XYZ footvel, footpoint;
3489 footpoint = weapons[weaponids[0]].tippoint;
3491 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3492 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3493 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3494 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3495 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3496 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3500 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3501 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3502 award_bonus(id, backstab);
3506 XYZ footvel, footpoint;
3508 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3510 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3511 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3512 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3513 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3514 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3515 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3516 victim->DoBloodBig(200, 180);
3517 victim->DoBloodBig(200, 215);
3518 victim->bloodloss += 10000;
3519 victim->velocity = 0;
3520 emit_sound_at(fleshstabsound, victim->coords);
3522 weapons[weaponids[weaponactive]].bloody = 2;
3523 weapons[weaponids[weaponactive]].blooddrip += 5;
3527 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3529 victim->velocity = 0;
3530 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3531 victim->skeleton.joints[i].velocity = 0;
3533 if (weaponactive != -1) {
3534 emit_sound_at(fleshstabremovesound, victim->coords);
3536 weapons[weaponids[weaponactive]].bloody = 2;
3537 weapons[weaponids[weaponactive]].blooddrip += 5;
3539 XYZ footvel, footpoint;
3541 footpoint = weapons[weaponids[0]].tippoint;
3543 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3544 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3545 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3546 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3547 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3548 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3552 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3560 if (weaponactive == -1) {
3561 if (tutoriallevel != 1) {
3562 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3567 if (weaponactive != -1 || creature == wolftype)
3569 if (creature == rabbittype && weaponactive != -1)
3570 if (weapons[weaponids[0]].getType() == staff)
3573 if (weaponactive != -1) {
3574 victim->DoBloodBig(2 / victim->armorhead, 225);
3575 emit_sound_at(knifeslicesound, victim->coords);
3576 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3577 weapons[weaponids[weaponactive]].bloody = 1;
3578 weapons[weaponids[weaponactive]].blooddrip += 3;
3580 if (weaponactive == -1 && creature == wolftype) {
3581 emit_sound_at(clawslicesound, victim->coords, 128.);
3583 victim->DoBloodBig(2 / victim->armorhead, 175);
3587 award_bonus(id, Reversal);
3592 relative = facing * -1;
3594 Normalise(&relative);
3595 relative = DoRotation(relative, 0, 90, 0);
3597 Normalise(&relative);
3598 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3599 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3601 victim->jointVel(head) += relative * damagemult * 200;
3602 if (victim->damage < victim->damagetolerance - 100)
3603 victim->velocity = relative * 200;
3604 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3605 victim->velocity = 0;
3608 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
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;
3624 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3625 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3626 award_bonus(id, reverseko);
3632 if (frameTarget > animation[animCurrent].numframes - 1) {
3635 animTarget = getIdle();
3639 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3640 animTarget = rollanim;
3642 emit_sound_at(movewhooshsound, coords, 128.);
3644 if (animCurrent == staggerbackhighanim) {
3645 animTarget = getIdle();
3647 if (animCurrent == staggerbackhardanim) {
3648 animTarget = getIdle();
3650 if (animCurrent == removeknifeanim) {
3651 animTarget = getIdle();
3653 if (animCurrent == crouchremoveknifeanim) {
3654 animTarget = getCrouch();
3656 if (animCurrent == backhandspringanim) {
3657 animTarget = getIdle();
3659 if (animCurrent == dodgebackanim) {
3660 animTarget = getIdle();
3662 if (animCurrent == drawleftanim) {
3663 animTarget = getIdle();
3665 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3666 animTarget = getIdle();
3667 if (animCurrent == crouchdrawrightanim) {
3668 animTarget = getCrouch();
3670 if (weaponactive == -1)
3672 else if (weaponactive == 0) {
3674 if (num_weapons == 2) {
3676 buffer = weaponids[0];
3677 weaponids[0] = weaponids[1];
3678 weaponids[1] = buffer;
3682 if (weaponactive == -1) {
3683 emit_sound_at(knifesheathesound, coords, 128.);
3685 if (weaponactive != -1) {
3686 emit_sound_at(knifedrawsound, coords, 128.);
3689 if (animCurrent == rollanim) {
3690 animTarget = getCrouch();
3695 if (animTarget == walljumprightkickanim) {
3698 if (animTarget == walljumpleftkickanim) {
3701 animTarget = jumpdownanim;
3703 if (animCurrent == climbanim) {
3704 animTarget = getCrouch();
3706 coords += facing * .1;
3707 if (!isnormal(coords.x))
3718 if (animTarget == rabbitkickreversalanim) {
3719 animTarget = getCrouch();
3722 if (animTarget == jumpreversalanim) {
3723 animTarget = getCrouch();
3726 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3727 if (attackkeydown && animTarget != walljumpfrontanim) {
3729 float closestdist = -1;
3731 if (Person::players.size() > 1)
3732 for (unsigned i = 0; i < Person::players.size(); i++) {
3733 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3734 distance = distsq(&Person::players[i]->coords, &coords);
3735 if (closestdist == -1 || distance < closestdist) {
3736 closestdist = distance;
3741 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3742 victim = Person::players[closest];
3743 animTarget = walljumprightkickanim;
3745 XYZ rotatetarget = victim->coords - coords;
3746 Normalise(&rotatetarget);
3747 yaw = -asin(0 - rotatetarget.x);
3749 if (rotatetarget.z < 0)
3751 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3752 velocity = (victim->coords - coords) * 4;
3757 if (animTarget == walljumpbackanim) {
3758 animTarget = backflipanim;
3760 velocity = facing * -8;
3763 resume_stream(whooshsound);
3765 if (animTarget == walljumprightanim) {
3766 animTarget = rightflipanim;
3770 velocity = DoRotation(facing, 0, 30, 0) * -8;
3773 if (animTarget == walljumpfrontanim) {
3774 animTarget = frontflipanim;
3778 velocity = facing * 8;
3782 resume_stream(whooshsound);
3784 if (animTarget == walljumpleftanim) {
3785 if (attackkeydown) {
3787 float closestdist = -1;
3789 if (Person::players.size() > 1)
3790 for (unsigned i = 0; i < Person::players.size(); i++) {
3791 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3792 distance = distsq(&Person::players[i]->coords, &coords);
3793 if (closestdist == -1 || distance < closestdist) {
3794 closestdist = distance;
3799 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3800 victim = Person::players[closest];
3801 animTarget = walljumpleftkickanim;
3803 XYZ rotatetarget = victim->coords - coords;
3804 Normalise(&rotatetarget);
3805 yaw = -asin(0 - rotatetarget.x);
3807 if (rotatetarget.z < 0)
3809 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3810 velocity = (victim->coords - coords) * 4;
3815 if (animTarget != walljumpleftkickanim) {
3816 animTarget = leftflipanim;
3820 velocity = DoRotation(facing, 0, -30, 0) * -8;
3824 resume_stream(whooshsound);
3826 if (animTarget == sneakattackanim) {
3827 animCurrent = getCrouch();
3828 animTarget = getCrouch();
3835 transspeed = 1000000;
3836 targetheadyaw += 180;
3837 coords -= facing * .7;
3839 coords.y = terrain.getHeight(coords.x, coords.z);
3843 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3844 animTarget = getIdle();
3847 coords.y = terrain.getHeight(coords.x, coords.z);
3851 if (animCurrent == knifefollowanim) {
3852 animTarget = getIdle();
3855 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3856 float ycoords = oldcoords.y;
3857 animTarget = getStop();
3862 transspeed = 1000000;
3863 targetheadyaw += 180;
3864 if (!isnormal(coords.x))
3866 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3867 oldcoords = coords + facing * .5;
3868 else if (animCurrent == sweepreversalanim)
3869 oldcoords = coords + facing * 1.1;
3870 else if (animCurrent == upunchreversalanim) {
3871 oldcoords = coords + facing * 1.5;
3874 targetheadyaw += 180;
3877 } else if (animCurrent == knifeslashreversalanim) {
3878 oldcoords = coords + facing * .5;
3881 targetheadyaw += 90;
3884 } else if (animCurrent == staffspinhitreversalanim) {
3887 targetheadyaw += 180;
3892 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3894 oldcoords.y = ycoords;
3895 currentoffset = coords - oldcoords;
3901 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3906 if (animation[animTarget].attack == reversed) {
3908 if (animTarget == sweepreversedanim)
3910 animTarget = backhandspringanim;
3912 emit_sound_at(landsound, coords, 128);
3914 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3915 animTarget = rollanim;
3918 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3919 coords.y = oldcoords.y;
3921 if (animCurrent == knifeslashreversedanim) {
3922 animTarget = rollanim;
3927 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3928 coords.y = oldcoords.y;
3932 animTarget = jumpdownanim;
3935 animTarget = getIdle();
3937 animTarget = getIdle();
3938 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3939 animTarget = getIdle();
3941 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3942 coords.y = oldcoords.y;
3943 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3944 targetoffset.y = coords.y;
3946 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3947 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3948 currentoffset.y -= (coords.y - targetoffset.y);
3949 coords.y = targetoffset.y;
3951 normalsupdatedelay = 0;
3953 if (animCurrent == upunchanim) {
3954 animTarget = getStop();
3955 normalsupdatedelay = 0;
3958 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3962 if (num_weapons > 0)
3963 if (weapons[0].getType() == staff)
3969 rabbitkickragdoll = 1;
3971 if (animCurrent == rabbitkickreversedanim) {
3977 skeleton.spinny = 0;
3978 SolidHitBonus(!id); // FIXME: tricky id
3982 animTarget = rollanim;
3985 pause_sound(whooshsound);
3989 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3993 skeleton.spinny = 0;
3995 if (animCurrent == jumpreversedanim) {
4001 skeleton.spinny = 0;
4002 SolidHitBonus(!id); // FIXME: tricky id
4006 animTarget = rollanim;
4007 coords += facing * 2;
4009 pause_sound(whooshsound);
4014 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) {
4015 animTarget = getupfromfrontanim;
4017 } else if (animation[animCurrent].attack == normalattack) {
4018 animTarget = getIdle();
4021 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4022 animTarget = blockhighleftstrikeanim;
4024 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4025 animTarget = getIdle();
4028 if (animCurrent == spinkickanim && victim->skeleton.free) {
4029 if (creature == rabbittype)
4030 animTarget = fightidleanim;
4035 if (isIdle() && !wasIdle())
4036 normalsupdatedelay = 0;
4038 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4039 animTarget = jumpdownanim;
4042 if (!skeleton.free) {
4044 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4045 if (!isRun() || !wasRun()) {
4046 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4047 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4048 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4049 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4051 if (isRun() && wasRun()) {
4053 tempspeed = velspeed;
4054 if (tempspeed < 10 * speedmult)
4055 tempspeed = 10 * speedmult;
4056 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4058 } else if (transspeed)
4059 target += multiplier * transspeed * speed * 2;
4061 if (!isRun() || !wasRun()) {
4062 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4063 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4064 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4065 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4069 if (animCurrent != animTarget)
4070 target = (target + oldtarget) / 2;
4073 frameCurrent = frameTarget;
4077 rot = targetrot * target;
4078 yaw += rot - oldrot;
4084 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4086 for (int i = 0; i < skeleton.num_joints; i++) {
4087 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4090 skeleton.FindForwards();
4092 for (int i = 0; i < skeleton.num_muscles; i++) {
4093 if (skeleton.muscles[i].visible) {
4094 skeleton.FindRotationMuscle(i, animTarget);
4097 for (int i = 0; i < skeleton.num_muscles; i++) {
4098 if (skeleton.muscles[i].visible) {
4099 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4100 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4101 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4102 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4103 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4104 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4109 for (int i = 0; i < skeleton.num_joints; i++) {
4110 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4113 skeleton.FindForwards();
4115 for (int i = 0; i < skeleton.num_muscles; i++) {
4116 if (skeleton.muscles[i].visible) {
4117 skeleton.FindRotationMuscle(i, animTarget);
4120 for (int i = 0; i < skeleton.num_muscles; i++) {
4121 if (skeleton.muscles[i].visible) {
4122 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4123 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4124 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4125 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4126 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4127 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4128 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4129 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4130 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4131 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4132 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4133 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4137 if (frameCurrent >= animation[animCurrent].numframes)
4138 frameCurrent = animation[animCurrent].numframes - 1;
4140 oldanimCurrent = animCurrent;
4141 oldanimTarget = animTarget;
4142 oldframeTarget = frameTarget;
4143 oldframeCurrent = frameCurrent;
4145 for (int i = 0; i < skeleton.num_joints; i++) {
4146 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4147 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4149 offset = currentoffset * (1 - target) + targetoffset * target;
4150 for (int i = 0; i < skeleton.num_muscles; i++) {
4151 if (skeleton.muscles[i].visible) {
4152 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4153 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4154 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4159 if (isLanding() && landhard) {
4162 animTarget = getLandhard();
4175 void Person::DoStuff()
4177 static XYZ terrainnormal;
4178 static XYZ flatfacing;
4179 static XYZ flatvelocity;
4180 static float flatvelspeed;
4184 static int bloodsize;
4185 static int startx, starty, endx, endy;
4186 static GLubyte color;
4187 static XYZ bloodvel;
4189 onfiredelay -= multiplier;
4190 if (onfiredelay < 0 && onfire) {
4191 if (Random() % 2 == 0) {
4197 crouchkeydowntime += multiplier;
4199 crouchkeydowntime = 0;
4200 jumpkeydowntime += multiplier;
4201 if (!jumpkeydown && skeleton.free)
4202 jumpkeydowntime = 0;
4204 if (hostile || damage > 0 || bloodloss > 0)
4207 if (isIdle() || isRun())
4210 if (num_weapons == 1 && weaponactive != -1)
4214 blooddimamount -= multiplier * .3;
4215 speechdelay -= multiplier;
4216 texupdatedelay -= multiplier;
4217 interestdelay -= multiplier;
4218 flamedelay -= multiplier;
4219 parriedrecently -= multiplier;
4221 victim = this->shared_from_this();
4226 speed = 1.1 * speedmult;
4228 speed = 1.0 * speedmult;
4230 rabbitkickragdoll = 0;
4234 if (id != 0 && (creature == rabbittype || difficulty != 2))
4236 if (id != 0 && creature == wolftype && difficulty == 2) {
4238 if (aitype != passivetype) {
4240 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) {
4246 if (animTarget == wolfrunninganim && !superruntoggle) {
4247 animTarget = getRun();
4251 if (weaponactive == -1 && num_weapons > 0) {
4252 if (weapons[weaponids[0]].getType() == staff) {
4258 burnt += multiplier;
4262 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4264 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4270 vel[0] = velocity.x;
4271 vel[1] = velocity.y;
4272 vel[2] = velocity.z;
4275 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4276 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4280 while (flamedelay < 0 && onfire) {
4282 howmany = abs(Random() % (skeleton.num_joints));
4283 if (skeleton.free) {
4284 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4285 flatfacing = skeleton.joints[howmany].position * scale + coords;
4287 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4288 flatvelocity = (coords - oldcoords) / multiplier / 2;
4290 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4293 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4295 howmany = abs(Random() % (skeleton.num_joints));
4296 if (skeleton.free) {
4297 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4298 flatfacing = skeleton.joints[howmany].position * scale + coords;
4300 flatvelocity = (coords - oldcoords) / multiplier / 2;
4301 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4303 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4307 bleeding -= multiplier * .3;
4308 if (bloodtoggle == 2) {
4309 skeleton.drawmodel.textureptr.bind();
4310 if ((bleeding <= 0) && (detail != 2))
4315 if (neckspurtamount > 0) {
4316 neckspurtamount -= multiplier;
4317 neckspurtdelay -= multiplier * 3;
4318 neckspurtparticledelay -= multiplier * 3;
4319 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4322 if (skeleton.free) {
4323 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4324 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4325 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4327 bloodvel.z = 5 * neckspurtamount;
4328 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4329 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4330 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4332 neckspurtparticledelay = .05;
4334 if (neckspurtdelay < 0) {
4339 if (deathbleeding > 0 && dead != 2) {
4340 if (deathbleeding < 5)
4341 bleeddelay -= deathbleeding * multiplier / 4;
4343 bleeddelay -= 5 * multiplier / 4;
4344 if (bleeddelay < 0 && bloodtoggle) {
4349 if (skeleton.free) {
4350 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4351 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4353 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4354 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4358 bloodloss += deathbleeding * multiplier * 80;
4359 deathbleeding -= multiplier * 1.6;
4360 if (deathbleeding < 0)
4362 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4363 if (weaponactive != -1) {
4364 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4365 weapons[weaponids[0]].velocity.x += .01;
4368 weaponids[0] = weaponids[num_weapons];
4369 if (weaponstuck == num_weapons)
4373 for (unsigned i = 0; i < Person::players.size(); i++) {
4374 Person::players[i]->wentforweapon = 0;
4386 if (!dead && creature == wolftype) {
4387 award_bonus(0, Wolfbonus);
4390 if (animTarget == knifefollowedanim && !skeleton.free) {
4391 for (int i = 0; i < skeleton.num_joints; i++) {
4392 skeleton.joints[i].velocity = 0;
4393 skeleton.joints[i].velocity.y = -2;
4396 if (id != 0 && unconscioustime > .1) {
4404 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4405 texupdatedelay = .12;
4407 bloodsize = 5 - realtexdetail;
4411 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4412 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4413 endx = startx + bloodsize;
4414 endy = starty + bloodsize;
4424 if (endx > skeleton.skinsize - 1) {
4425 endx = skeleton.skinsize - 1;
4428 if (endy > skeleton.skinsize - 1) {
4429 endy = skeleton.skinsize - 1;
4437 for (i = startx; i < endx; i++) {
4438 for (j = starty; j < endy; j++) {
4439 if (Random() % 2 == 0) {
4440 color = Random() % 85 + 170;
4441 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4442 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4443 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4444 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4449 skeleton.drawmodel.textureptr.bind();
4453 if (skeleton.free) {
4454 bleedx += 4 * direction / realtexdetail;
4456 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4458 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4460 bleedy -= 4 / realtexdetail;
4462 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4464 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4468 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4469 righthandmorphness = targetrighthandmorphness;
4470 righthandmorphstart = righthandmorphend;
4471 } else if (righthandmorphness > targetrighthandmorphness) {
4472 righthandmorphness -= multiplier * 4;
4473 } else if (righthandmorphness < targetrighthandmorphness) {
4474 righthandmorphness += multiplier * 4;
4477 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4478 lefthandmorphness = targetlefthandmorphness;
4479 lefthandmorphstart = lefthandmorphend;
4480 } else if (lefthandmorphness > targetlefthandmorphness) {
4481 lefthandmorphness -= multiplier * 4;
4482 } else if (lefthandmorphness < targetlefthandmorphness) {
4483 lefthandmorphness += multiplier * 4;
4486 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4487 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4488 tailmorphness = targettailmorphness;
4489 tailmorphstart = tailmorphend;
4490 } else if (tailmorphness > targettailmorphness) {
4491 tailmorphness -= multiplier * 10;
4492 } else if (tailmorphness < targettailmorphness) {
4493 tailmorphness += multiplier * 10;
4497 if (creature == wolftype) {
4498 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4499 tailmorphness = targettailmorphness;
4500 tailmorphstart = tailmorphend;
4501 } else if (tailmorphness > targettailmorphness) {
4502 tailmorphness -= multiplier * 2;
4503 } else if (tailmorphness < targettailmorphness) {
4504 tailmorphness += multiplier * 2;
4508 if (headmorphend == 3 || headmorphstart == 3) {
4509 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4510 headmorphness = targetheadmorphness;
4511 headmorphstart = headmorphend;
4512 } else if (headmorphness > targetheadmorphness) {
4513 headmorphness -= multiplier * 7;
4514 } else if (headmorphness < targetheadmorphness) {
4515 headmorphness += multiplier * 7;
4517 } else if (headmorphend == 5 || headmorphstart == 5) {
4518 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4519 headmorphness = targetheadmorphness;
4520 headmorphstart = headmorphend;
4521 } else if (headmorphness > targetheadmorphness) {
4522 headmorphness -= multiplier * 10;
4523 } else if (headmorphness < targetheadmorphness) {
4524 headmorphness += multiplier * 10;
4527 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4528 headmorphness = targetheadmorphness;
4529 headmorphstart = headmorphend;
4530 } else if (headmorphness > targetheadmorphness) {
4531 headmorphness -= multiplier * 4;
4532 } else if (headmorphness < targetheadmorphness) {
4533 headmorphness += multiplier * 4;
4537 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4538 chestmorphness = targetchestmorphness;
4539 chestmorphstart = chestmorphend;
4540 } else if (chestmorphness > targetchestmorphness) {
4541 chestmorphness -= multiplier;
4542 } else if (chestmorphness < targetchestmorphness) {
4543 chestmorphness += multiplier;
4546 if (dead != 2 && howactive <= typesleeping) {
4547 if (chestmorphstart == 0 && chestmorphend == 0) {
4549 targetchestmorphness = 1;
4552 if (chestmorphstart != 0 && chestmorphend != 0) {
4554 targetchestmorphness = 1;
4556 if (environment == snowyenvironment) {
4559 if (skeleton.free) {
4560 footvel = skeleton.specialforward[0] * -1;
4561 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4563 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4564 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4566 if (animTarget == sleepanim)
4567 footvel = DoRotation(footvel, 0, 90, 0);
4568 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4572 if (!dead && howactive < typesleeping) {
4573 blinkdelay -= multiplier * 2;
4574 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4576 targetheadmorphness = 1;
4578 blinkdelay = (float)(abs(Random() % 40)) / 5;
4580 if (headmorphstart == 3 && headmorphend == 3) {
4582 targetheadmorphness = 1;
4587 twitchdelay -= multiplier * 1.5;
4588 if (animTarget != hurtidleanim) {
4589 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4591 targetheadmorphness = 1;
4593 twitchdelay = (float)(abs(Random() % 40)) / 5;
4595 if (headmorphstart == 5 && headmorphend == 5) {
4597 targetheadmorphness = 1;
4601 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4602 twitchdelay3 -= multiplier * 1;
4603 if (Random() % 2 == 0) {
4604 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4605 righthandmorphness = 0;
4606 targetrighthandmorphness = 1;
4607 righthandmorphend = 1;
4608 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4610 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4611 righthandmorphness = 0;
4612 targetrighthandmorphness = 1;
4613 righthandmorphend = 0;
4616 if (Random() % 2 == 0) {
4617 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4618 lefthandmorphness = 0;
4619 targetlefthandmorphness = 1;
4620 lefthandmorphend = 1;
4621 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4623 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4624 lefthandmorphness = 0;
4625 targetlefthandmorphness = 1;
4626 lefthandmorphend = 0;
4632 if (creature == rabbittype) {
4633 if (howactive < typesleeping)
4634 twitchdelay2 -= multiplier * 1.5;
4636 twitchdelay2 -= multiplier * 0.5;
4637 if (howactive <= typesleeping) {
4638 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4640 targettailmorphness = 1;
4642 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4644 if (tailmorphstart == 1 && tailmorphend == 1) {
4646 targettailmorphness = 1;
4649 if (tailmorphstart == 2 && tailmorphend == 2) {
4651 targettailmorphness = 1;
4658 if (creature == wolftype) {
4659 twitchdelay2 -= multiplier * 1.5;
4660 if (tailmorphend != 0)
4661 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4663 targettailmorphness = 1;
4667 if (tailmorphend != 5)
4668 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4670 targettailmorphness = 1;
4674 if (twitchdelay2 <= 0) {
4675 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4677 targettailmorphness = 1;
4680 if (tailmorphstart == 1 && tailmorphend == 1) {
4682 targettailmorphness = 1;
4685 if (tailmorphstart == 2 && tailmorphend == 2) {
4687 targettailmorphness = 1;
4690 if (tailmorphstart == 3 && tailmorphend == 3) {
4692 targettailmorphness = 1;
4695 if (tailmorphstart == 4 && tailmorphend == 4) {
4697 targettailmorphness = 1;
4704 unconscioustime = 0;
4706 if (dead == 1 || howactive == typesleeping) {
4707 unconscioustime += multiplier;
4708 //If unconscious, close eyes and mouth
4709 if (righthandmorphend != 0)
4710 righthandmorphness = 0;
4711 righthandmorphend = 0;
4712 targetrighthandmorphness = 1;
4714 if (lefthandmorphend != 0)
4715 lefthandmorphness = 0;
4716 lefthandmorphend = 0;
4717 targetlefthandmorphness = 1;
4719 if (headmorphend != 3 && headmorphend != 5)
4722 targetheadmorphness = 1;
4726 if (howactive > typesleeping) {
4729 if (bloodtoggle && !bled) {
4730 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4732 if (bloodtoggle && !bled)
4733 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4734 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4735 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4739 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4744 if (dead == 2 || howactive > typesleeping) {
4745 //If dead, open mouth and hands
4746 if (righthandmorphend != 0)
4747 righthandmorphness = 0;
4748 righthandmorphend = 0;
4749 targetrighthandmorphness = 1;
4751 if (lefthandmorphend != 0)
4752 lefthandmorphness = 0;
4753 lefthandmorphend = 0;
4754 targetlefthandmorphness = 1;
4756 if (headmorphend != 2)
4759 targetheadmorphness = 1;
4762 if (stunned > 0 && !dead && headmorphend != 2) {
4763 if (headmorphend != 4)
4766 targetheadmorphness = 1;
4769 if (damage > damagetolerance && !dead) {
4772 unconscioustime = 0;
4774 if (creature == wolftype) {
4775 award_bonus(0, Wolfbonus);
4780 if (weaponactive != -1) {
4781 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4782 weapons[weaponids[0]].velocity.x += .01;
4785 weaponids[0] = weaponids[num_weapons];
4786 if (weaponstuck == num_weapons)
4790 for (unsigned i = 0; i < Person::players.size(); i++) {
4791 Person::players[i]->wentforweapon = 0;
4797 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4806 damage -= multiplier * 13;
4808 permanentdamage -= multiplier * 4;
4809 if (isIdle() || isCrouch()) {
4811 permanentdamage -= multiplier * 4;
4815 if (permanentdamage < 0)
4816 permanentdamage = 0;
4817 if (superpermanentdamage < 0)
4818 superpermanentdamage = 0;
4819 if (permanentdamage < superpermanentdamage) {
4820 permanentdamage = superpermanentdamage;
4822 if (damage < permanentdamage) {
4823 damage = permanentdamage;
4825 if (dead == 1 && damage < damagetolerance) {
4829 for (int i = 0; i < skeleton.num_joints; i++) {
4830 skeleton.joints[i].velocity = 0;
4833 if (permanentdamage > damagetolerance && dead != 2) {
4836 if (weaponactive != -1) {
4837 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4838 weapons[weaponids[0]].velocity.x += .01;
4841 weaponids[0] = weaponids[num_weapons];
4842 if (weaponstuck == num_weapons)
4846 for (unsigned i = 0; i < Person::players.size(); i++) {
4847 Person::players[i]->wentforweapon = 0;
4853 if (!dead && creature == wolftype) {
4854 award_bonus(0, Wolfbonus);
4857 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4858 award_bonus(id, touchofdeath);
4859 if (id != 0 && unconscioustime > .1) {
4867 emit_sound_at(breaksound, coords);
4870 if (skeleton.free == 1) {
4872 pause_sound(whooshsound);
4875 //If knocked over, open hands and close mouth
4876 if (righthandmorphend != 0)
4877 righthandmorphness = 0;
4878 righthandmorphend = 0;
4879 targetrighthandmorphness = 1;
4881 if (lefthandmorphend != 0)
4882 lefthandmorphness = 0;
4883 lefthandmorphend = 0;
4884 targetlefthandmorphness = 1;
4886 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4887 if (headmorphend != 0)
4890 targetheadmorphness = 1;
4894 skeleton.DoGravity(&scale);
4896 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4897 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4898 award_bonus(id, deepimpact);
4899 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4903 for (j = 0; j < skeleton.num_joints; j++) {
4904 average += skeleton.joints[j].position;
4908 coords += average * scale;
4909 for (j = 0; j < skeleton.num_joints; j++) {
4910 skeleton.joints[j].position -= average;
4912 average /= multiplier;
4915 for (int i = 0; i < skeleton.num_joints; i++) {
4916 velocity += skeleton.joints[i].velocity * scale;
4918 velocity /= skeleton.num_joints;
4920 if (!isnormal(velocity.x) && velocity.x) {
4924 if (findLength(&average) < 10 && dead && skeleton.free) {
4925 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4926 if (skeleton.longdead > 2000) {
4927 if (skeleton.longdead > 6000) {
4929 pause_sound(whooshsound);
4934 if (dead == 2 && bloodloss < damagetolerance) {
4936 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4938 if (bloodtoggle && !bled) {
4939 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4941 if (bloodtoggle && !bled)
4942 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4943 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4944 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4945 float size = .2 * 1.2;
4948 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4952 if (dead == 2 && bloodloss >= damagetolerance) {
4954 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4957 if (bloodtoggle && !bled) {
4958 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4960 if (bloodtoggle && !bled)
4961 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4962 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4963 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4967 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4974 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4975 bool canrecover = 1;
4976 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4977 startpoint = coords;
4980 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4982 if (velocity.y < -30)
4984 for (i = 0; i < objects.numobjects; i++) {
4985 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4986 colviewer = startpoint;
4987 coltarget = endpoint;
4988 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4997 terrainnormal = jointPos(groin) - jointPos(abdomen);
4998 if (joint(groin).locked && joint(abdomen).locked) {
4999 terrainnormal = jointPos(groin) - jointPos(abdomen);
5000 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5002 if (joint(abdomen).locked && joint(neck).locked) {
5003 terrainnormal = jointPos(abdomen) - jointPos(neck);
5004 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5006 if (joint(groin).locked && joint(neck).locked) {
5007 terrainnormal = jointPos(groin) - jointPos(neck);
5008 middle = (jointPos(groin) + jointPos(neck)) / 2;
5010 Normalise(&terrainnormal);
5012 targetyaw = -asin(0 - terrainnormal.x);
5013 targetyaw *= 360 / 6.28;
5014 if (terrainnormal.z < 0)
5015 targetyaw = 180 - targetyaw;
5019 animTarget = flipanim;
5020 crouchtogglekeydown = 1;
5025 animCurrent = tempanim;
5029 for (int i = 0; i < skeleton.num_joints; i++) {
5030 tempanimation.position[i][0] = skeleton.joints[i].position;
5031 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5036 if (findLength(&average) < 10 && !dead && skeleton.free) {
5037 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5038 if (skeleton.longdead > (damage + 500) * 1.5) {
5040 pause_sound(whooshsound);
5046 terrainnormal = jointPos(groin) - jointPos(abdomen);
5047 if (joint(groin).locked && joint(abdomen).locked) {
5048 terrainnormal = jointPos(groin) - jointPos(abdomen);
5049 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5051 if (joint(abdomen).locked && joint(neck).locked) {
5052 terrainnormal = jointPos(abdomen) - jointPos(neck);
5053 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5055 if (joint(groin).locked && joint(neck).locked) {
5056 terrainnormal = jointPos(groin) - jointPos(neck);
5057 middle = (jointPos(groin) + jointPos(neck)) / 2;
5059 Normalise(&terrainnormal);
5061 targetyaw = -asin(0 - terrainnormal.x);
5062 targetyaw *= 360 / 6.28;
5063 if (terrainnormal.z < 0)
5064 targetyaw = 180 - targetyaw;
5067 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5070 if (skeleton.forward.y < 0) {
5071 animTarget = getupfrombackanim;
5075 if (skeleton.forward.y > -.3) {
5076 animTarget = getupfromfrontanim;
5084 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5085 animTarget = rollanim;
5086 targetyaw = lookyaw;
5103 if ( !leftkeydown && !rightkeydown)
5110 if (abs(targettilt2) > 50)
5112 animCurrent = tempanim;
5115 tilt2 = targettilt2;
5117 if (middle.y > 0 && animTarget != rollanim)
5118 targetoffset.y = middle.y + 1;
5120 for (int i = 0; i < skeleton.num_joints; i++) {
5121 tempanimation.position[i][0] = skeleton.joints[i].position;
5122 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5129 if (num_weapons > 0)
5130 if (weapons[0].getType() == staff)
5132 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5133 if (velocity.y > -30) {
5135 tempvelocity = velocity;
5136 Normalise(&tempvelocity);
5137 targetyaw = -asin(0 - tempvelocity.x);
5138 targetyaw *= 360 / 6.28;
5140 targetyaw = 180 - targetyaw;
5144 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5145 animTarget = rollanim;
5148 animTarget = backhandspringanim;
5154 emit_sound_at(movewhooshsound, coords, 128.);
5156 animCurrent = animTarget;
5157 frameCurrent = frameTarget - 1;
5169 if (skeleton.freefall == 0)
5174 if (aitype != passivetype || skeleton.free == 1)
5175 if (findLengthfast(&velocity) > .1)
5176 for (i = 0; i < objects.numobjects; i++) {
5177 if (objects.type[i] == firetype)
5178 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) {
5180 if (!objects.onfire[i]) {
5181 emit_sound_at(firestartsound, objects.position[i]);
5183 objects.onfire[i] = 1;
5186 if (objects.onfire[i]) {
5191 if (objects.type[i] == bushtype)
5192 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) {
5194 if (!objects.onfire[i]) {
5195 emit_sound_at(firestartsound, objects.position[i]);
5197 objects.onfire[i] = 1;
5201 if (objects.onfire[i]) {
5205 if (objects.messedwith[i] <= 0) {
5209 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5212 addEnvSound(coords, 4 * findLength(&velocity));
5216 if (environment == grassyenvironment)
5217 howmany = findLength(&velocity) * 4;
5218 if (environment == snowyenvironment)
5219 howmany = findLength(&velocity) * 2;
5221 if (environment != desertenvironment)
5222 for (j = 0; j < howmany; j++) {
5223 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5224 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5225 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5228 pos.x += float(abs(Random() % 100) - 50) / 200;
5229 pos.y += float(abs(Random() % 100) - 50) / 200;
5230 pos.z += float(abs(Random() % 100) - 50) / 200;
5231 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);
5232 Sprite::setLastSpriteSpecial(1);
5234 howmany = findLength(&velocity) * 4;
5236 if (environment == snowyenvironment)
5237 for (j = 0; j < howmany; j++) {
5238 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5239 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5240 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5243 pos.x += float(abs(Random() % 100) - 50) / 200;
5244 pos.y += float(abs(Random() % 100) - 50) / 200;
5245 pos.z += float(abs(Random() % 100) - 50) / 200;
5246 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5247 Sprite::setLastSpriteSpecial(2);
5250 objects.rotx[i] += velocity.x * multiplier * 6;
5251 objects.roty[i] += velocity.z * multiplier * 6;
5252 objects.messedwith[i] = .5;
5255 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5256 if (objects.pitch[i] == 0)
5259 tempcoord = coords - objects.position[i];
5260 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5261 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5262 tempcoord += objects.position[i];
5264 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]) {
5265 if (objects.messedwith[i] <= 0) {
5269 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5272 addEnvSound(coords, 4 * findLength(&velocity));
5276 if (environment == grassyenvironment)
5277 howmany = findLength(&velocity) * 4;
5278 if (environment == snowyenvironment)
5279 howmany = findLength(&velocity) * 2;
5281 if (environment != desertenvironment)
5282 for (j = 0; j < howmany; j++) {
5283 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5284 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5285 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5287 pos += velocity * .1;
5289 pos.x += float(abs(Random() % 100) - 50) / 150;
5290 pos.y += float(abs(Random() % 100) - 50) / 150;
5291 pos.z += float(abs(Random() % 100) - 50) / 150;
5292 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);
5293 Sprite::setLastSpriteSpecial(1);
5295 howmany = findLength(&velocity) * 4;
5297 if (environment == snowyenvironment)
5298 for (j = 0; j < howmany; j++) {
5299 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5300 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5301 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5303 pos += velocity * .1;
5305 pos.x += float(abs(Random() % 100) - 50) / 150;
5306 pos.y += float(abs(Random() % 100) - 50) / 150;
5307 pos.z += float(abs(Random() % 100) - 50) / 150;
5308 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5309 Sprite::setLastSpriteSpecial(2);
5312 objects.messedwith[i] = .5;
5317 if (!skeleton.free) {
5320 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5323 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5325 if (tutoriallevel == 1 && id != 0)
5327 if (play && aitype != playercontrolled) {
5328 int whichsound = -1;
5329 i = abs(Random() % 4);
5330 if (speechdelay <= 0) {
5331 if (creature == rabbittype) {
5333 whichsound = rabbitchitter;
5335 whichsound = rabbitchitter2;
5337 if (creature == wolftype) {
5339 whichsound = growlsound;
5341 whichsound = growl2sound;
5346 if (whichsound != -1) {
5347 emit_sound_at(whichsound, coords);
5351 if (animTarget == staggerbackhighanim)
5353 if (animTarget == staggerbackhardanim)
5355 staggerdelay -= multiplier;
5356 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5358 if (velocity.y < -30 && animTarget == jumpdownanim)
5360 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5361 animTarget = getIdle();
5365 weaponmissdelay -= multiplier;
5366 highreversaldelay -= multiplier;
5367 lowreversaldelay -= multiplier;
5368 lastcollide -= multiplier;
5369 skiddelay -= multiplier;
5370 if (!isnormal(velocity.x) && velocity.x) {
5373 if (!isnormal(targettilt) && targettilt) {
5376 if (!isnormal(targettilt2) && targettilt2) {
5379 if (!isnormal(targetyaw) && targetyaw) {
5383 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5384 //open hands and close mouth
5385 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5386 righthandmorphness = 0;
5387 righthandmorphend = 0;
5388 targetrighthandmorphness = 1;
5391 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5392 lefthandmorphness = 0;
5393 lefthandmorphend = 0;
5394 targetlefthandmorphness = 1;
5397 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5400 targetheadmorphness = 1;
5404 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) {
5405 //open hands and mouth
5406 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5407 righthandmorphness = 0;
5408 righthandmorphend = 0;
5409 targetrighthandmorphness = 1;
5412 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5413 lefthandmorphness = 0;
5414 lefthandmorphend = 0;
5415 targetlefthandmorphness = 1;
5418 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5421 targetheadmorphness = 1;
5425 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5426 //close hands and mouth
5427 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5428 righthandmorphness = 0;
5429 righthandmorphend = 1;
5430 targetrighthandmorphness = 1;
5433 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5434 lefthandmorphness = 0;
5435 lefthandmorphend = 1;
5436 targetlefthandmorphness = 1;
5439 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5442 targetheadmorphness = 1;
5446 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) {
5447 //close hands and yell
5448 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5449 righthandmorphness = 0;
5450 righthandmorphend = 1;
5451 targetrighthandmorphness = 1;
5454 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5455 lefthandmorphness = 0;
5456 lefthandmorphend = 1;
5457 targetlefthandmorphness = 1;
5460 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5463 targetheadmorphness = 1;
5470 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5471 (victim->aitype != searchtype) && (aitype != passivetype) &&
5472 (aitype != searchtype) && (victim->id < Person::players.size())) {
5473 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5477 if (!dead && animTarget != hurtidleanim)
5478 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5479 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5482 targetheadmorphness = 1;
5486 if (weaponactive != -1) {
5487 if (weapons[weaponids[weaponactive]].getType() != staff) {
5488 righthandmorphstart = 1;
5489 righthandmorphend = 1;
5491 if (weapons[weaponids[weaponactive]].getType() == staff) {
5492 righthandmorphstart = 2;
5493 righthandmorphend = 2;
5495 targetrighthandmorphness = 1;
5498 terrainnormal = terrain.getNormal(coords.x, coords.z);
5500 if (animation[animTarget].attack != reversal) {
5501 if (!isnormal(coords.x))
5509 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5510 facing = flatfacing;
5511 ReflectVector(&facing, terrainnormal);
5514 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5516 targettilt2 = -facing.y * 20;
5521 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5523 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5524 flatvelocity = velocity;
5526 flatvelspeed = findLength(&flatvelocity);
5527 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5528 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5533 if (targettilt > 25)
5535 if (targettilt < -25)
5539 if (targettilt2 > 45)
5541 if (targettilt2 < -45)
5543 if (abs(tilt2 - targettilt2) < multiplier * 400)
5544 tilt2 = targettilt2;
5545 else if (tilt2 > targettilt2) {
5546 tilt2 -= multiplier * 400;
5547 } else if (tilt2 < targettilt2) {
5548 tilt2 += multiplier * 400;
5550 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5557 if (!isnormal(targettilt) && targettilt) {
5560 if (!isnormal(targettilt2) && targettilt2) {
5565 if (animTarget == rabbittackleanim) {
5566 velocity += facing * multiplier * speed * 700 * scale;
5567 velspeed = findLength(&velocity);
5568 if (velspeed > speed * 65 * scale) {
5569 velocity /= velspeed;
5570 velspeed = speed * 65 * scale;
5571 velocity *= velspeed;
5573 velocity.y += gravity * multiplier * 20;
5574 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5575 velspeed = findLength(&velocity);
5576 velocity = flatfacing * velspeed;
5578 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5579 if (isRun() || animTarget == rabbitkickanim) {
5580 velocity += facing * multiplier * speed * 700 * scale;
5581 velspeed = findLength(&velocity);
5582 if (velspeed > speed * 45 * scale) {
5583 velocity /= velspeed;
5584 velspeed = speed * 45 * scale;
5585 velocity *= velspeed;
5587 velocity.y += gravity * multiplier * 20;
5588 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5589 velspeed = findLength(&velocity);
5590 if (velspeed < speed * 30 * scale)
5591 velspeed = speed * 30 * scale;
5592 velocity = flatfacing * velspeed;
5594 } else if (isRun()) {
5595 velocity += facing * multiplier * speed * 700 * scale;
5596 velspeed = findLength(&velocity);
5597 if (creature == rabbittype) {
5598 if (velspeed > speed * 55 * scale) {
5599 velocity /= velspeed;
5600 velspeed = speed * 55 * scale;
5601 velocity *= velspeed;
5604 if (creature == wolftype) {
5605 if (velspeed > speed * 75 * scale) {
5606 velocity /= velspeed;
5607 velspeed = speed * 75 * scale;
5608 velocity *= velspeed;
5611 velocity.y += gravity * multiplier * 20;
5612 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5613 velspeed = findLength(&velocity);
5614 velocity = flatfacing * velspeed;
5617 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5618 velocity += facing * multiplier * speed * 700 * scale;
5619 velspeed = findLength(&velocity);
5620 if (velspeed > speed * 45 * scale) {
5621 velocity /= velspeed;
5622 velspeed = speed * 45 * scale;
5623 velocity *= velspeed;
5625 velocity.y += gravity * multiplier * 20;
5626 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5627 velspeed = findLength(&velocity);
5628 velocity = flatfacing * velspeed;
5631 if (animTarget == sneakanim || animTarget == walkanim) {
5632 velocity += facing * multiplier * speed * 700 * scale;
5633 velspeed = findLength(&velocity);
5634 if (velspeed > speed * 12 * scale) {
5635 velocity /= velspeed;
5636 velspeed = speed * 12 * scale;
5637 velocity *= velspeed;
5639 velocity.y += gravity * multiplier * 20;
5640 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5641 velspeed = findLength(&velocity);
5642 velocity = flatfacing * velspeed;
5645 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5646 velocity += facing * multiplier * speed * 700 * scale;
5647 velspeed = findLength(&velocity);
5648 if (velspeed > speed * 2 * scale) {
5649 velocity /= velspeed;
5650 velspeed = speed * 2 * scale;
5651 velocity *= velspeed;
5653 velocity.y += gravity * multiplier * 20;
5654 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5655 velspeed = findLength(&velocity);
5656 velocity = flatfacing * velspeed;
5660 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5661 velocity -= facing * multiplier * speed * 700 * scale;
5662 velspeed = findLength(&velocity);
5663 if (velspeed > speed * 2 * scale) {
5664 velocity /= velspeed;
5665 velspeed = speed * 2 * scale;
5666 velocity *= velspeed;
5668 velocity.y += gravity * multiplier * 20;
5669 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5670 velspeed = findLength(&velocity);
5671 velocity = flatfacing * velspeed * -1;
5674 if (animTarget == fightsidestep) {
5675 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5676 velspeed = findLength(&velocity);
5677 if (velspeed > speed * 12 * scale) {
5678 velocity /= velspeed;
5679 velspeed = speed * 12 * scale;
5680 velocity *= velspeed;
5682 velocity.y += gravity * multiplier * 20;
5683 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5684 velspeed = findLength(&velocity);
5685 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5688 if (animTarget == staggerbackhighanim) {
5689 coords -= facing * multiplier * speed * 16 * scale;
5692 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5693 coords -= facing * multiplier * speed * 20 * scale;
5697 if (animTarget == backhandspringanim) {
5698 //coords-=facing*multiplier*50*scale;
5699 velocity += facing * multiplier * speed * 700 * scale * -1;
5700 velspeed = findLength(&velocity);
5701 if (velspeed > speed * 50 * scale) {
5702 velocity /= velspeed;
5703 velspeed = speed * 50 * scale;
5704 velocity *= velspeed;
5706 velocity.y += gravity * multiplier * 20;
5707 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5708 velspeed = findLength(&velocity);
5709 velocity = flatfacing * velspeed * -1;
5711 if (animTarget == dodgebackanim) {
5712 //coords-=facing*multiplier*50*scale;
5713 velocity += facing * multiplier * speed * 700 * scale * -1;
5714 velspeed = findLength(&velocity);
5715 if (velspeed > speed * 60 * scale) {
5716 velocity /= velspeed;
5717 velspeed = speed * 60 * scale;
5718 velocity *= velspeed;
5720 velocity.y += gravity * multiplier * 20;
5721 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5722 velspeed = findLength(&velocity);
5723 velocity = flatfacing * velspeed * -1;
5726 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5727 velspeed = findLength(&velocity);
5731 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5732 velocity.y += gravity * multiplier;
5735 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5736 coords += velocity * multiplier;
5738 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5739 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5742 if (animTarget == jumpupanim) {
5744 animTarget = getIdle();
5751 pause_sound(whooshsound);
5752 OPENAL_SetVolume(channels[whooshsound], 0);
5755 if (animTarget == jumpdownanim || isFlip()) {
5756 if (isFlip())jumppower = -4;
5757 animTarget = getLanding();
5758 emit_sound_at(landsound, coords, 128.);
5761 addEnvSound(coords);
5766 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5767 coords.y += gravity * multiplier * 2;
5768 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5769 coords.y = terrain.getHeight(coords.x, coords.z);
5774 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)) {
5775 velspeed = findLength(&velocity);
5777 if (velspeed < multiplier * 300 * scale) {
5780 velocity -= velocity / velspeed * multiplier * 300 * scale;
5781 if (velspeed > 5 && (isLanding() || isLandhard())) {
5782 skiddingdelay += multiplier;
5783 if (skiddelay <= 0) {
5793 velspeed = findLength(&velocity);
5795 if (velspeed < multiplier * 600 * scale) {
5798 velocity -= velocity / velspeed * multiplier * 600 * scale;
5800 if (velspeed > 5 && (isLanding() || isLandhard())) {
5801 skiddingdelay += multiplier;
5802 if (skiddelay <= 0) {
5811 if (skiddingdelay < 0)
5812 skiddingdelay += multiplier;
5813 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5815 if (!onterrain || environment == grassyenvironment) {
5816 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5818 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5822 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5823 terrainnormal = victim->coords - coords;
5824 Normalise(&terrainnormal);
5825 targetyaw = -asin(0 - terrainnormal.x);
5826 targetyaw *= 360 / 6.28;
5827 if (terrainnormal.z < 0)
5828 targetyaw = 180 - targetyaw;
5829 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5832 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5833 targetyaw = victim->targetyaw;
5835 if (animTarget == rabbittacklinganim) {
5836 coords = victim->coords;
5839 skeleton.oldfree = skeleton.free;
5843 midterrain.x = terrain.size * terrain.scale / 2;
5844 midterrain.z = terrain.size * terrain.scale / 2;
5845 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5847 tempposit = coords - midterrain;
5849 Normalise(&tempposit);
5850 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5851 coords.x = tempposit.x + midterrain.x;
5852 coords.z = tempposit.z + midterrain.z;
5858 * inverse kinematics helper function
5860 void IKHelper(Person *p, float interp)
5862 XYZ point, change, change2;
5863 float heightleft, heightright;
5865 // TODO: implement localToWorld and worldToLocal
5866 // but keep in mind it won't be the same math if player is ragdolled or something
5867 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5868 // then comb through code for places where to use it
5870 // point = localToWorld(jointPos(leftfoot))
5871 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5872 // adjust height of foot
5873 heightleft = terrain.getHeight(point.x, point.z) + .04;
5874 point.y = heightleft;
5875 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5876 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5877 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5878 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5879 // move ankle along with foot
5880 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5881 // average knee pos between old and new pos
5882 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5884 // do same as above for right leg
5885 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5886 heightright = terrain.getHeight(point.x, point.z) + .04;
5887 point.y = heightright;
5888 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5889 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5890 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5891 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5892 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5894 // fix up skeleton now that we've moved body parts?
5895 p->skeleton.DoConstraints(&p->coords, &p->scale);
5902 int Person::DrawSkeleton()
5904 int oldplayerdetail;
5905 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5906 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5916 glAlphaFunc(GL_GREATER, 0.0001);
5918 float terrainheight;
5922 if (!isnormal(tilt))
5924 if (!isnormal(tilt2))
5926 oldplayerdetail = playerdetail;
5928 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5931 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5934 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5939 if (playerdetail != oldplayerdetail) {
5941 normalsupdatedelay = 0;
5943 static float updatedelaychange;
5944 static float morphness;
5945 static float framemult;
5947 skeleton.FindForwards();
5948 if (howactive == typesittingwall) {
5949 skeleton.specialforward[1] = 0;
5950 skeleton.specialforward[1].z = 1;
5956 static int weaponattachmuscle;
5957 static int weaponrotatemuscle;
5958 static XYZ weaponpoint;
5959 static int start, endthing;
5960 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5961 if (!isSleeping() && !isSitting()) {
5962 // TODO: give these meaningful names
5963 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5964 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5965 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5966 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5968 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5970 if (creature == wolftype)
5974 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5975 IKHelper(this, target);
5976 if (creature == wolftype)
5977 IKHelper(this, target);
5980 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5981 IKHelper(this, 1 - target);
5982 if (creature == wolftype)
5983 IKHelper(this, 1 - target);
5987 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()))
5990 targetheadyaw = -targetyaw;
5991 targetheadpitch = 0;
5992 if (animation[animTarget].attack == 3)
5993 targetheadyaw += 180;
5995 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5996 skeleton.drawmodel.vertex[i] = 0;
5997 skeleton.drawmodel.vertex[i].y = 999;
5999 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6000 skeleton.drawmodellow.vertex[i] = 0;
6001 skeleton.drawmodellow.vertex[i].y = 999;
6003 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6004 skeleton.drawmodelclothes.vertex[i] = 0;
6005 skeleton.drawmodelclothes.vertex[i].y = 999;
6007 for (int i = 0; i < skeleton.num_muscles; i++) {
6008 // convenience renames
6009 const int p1 = skeleton.muscles[i].parent1->label;
6010 const int p2 = skeleton.muscles[i].parent2->label;
6012 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6017 if (p1 == righthand || p2 == righthand) {
6018 morphness = righthandmorphness;
6019 start = righthandmorphstart;
6020 endthing = righthandmorphend;
6022 if (p1 == lefthand || p2 == lefthand) {
6023 morphness = lefthandmorphness;
6024 start = lefthandmorphstart;
6025 endthing = lefthandmorphend;
6027 if (p1 == head || p2 == head) {
6028 morphness = headmorphness;
6029 start = headmorphstart;
6030 endthing = headmorphend;
6032 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6033 morphness = chestmorphness;
6034 start = chestmorphstart;
6035 endthing = chestmorphend;
6037 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6038 morphness = tailmorphness;
6039 start = tailmorphstart;
6040 endthing = tailmorphend;
6043 skeleton.FindRotationMuscle(i, animTarget);
6044 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6045 glMatrixMode(GL_MODELVIEW);
6049 glRotatef(tilt2, 1, 0, 0);
6051 glRotatef(tilt, 0, 0, 1);
6054 glTranslatef(mid.x, mid.y, mid.z);
6056 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6057 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6059 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6060 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6062 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6063 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6065 if (playerdetail || skeleton.free == 3) {
6066 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6067 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6068 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6069 glMatrixMode(GL_MODELVIEW);
6071 if (p1 == abdomen || p2 == abdomen)
6072 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6073 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6074 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6075 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6076 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6077 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6078 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6079 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6080 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6081 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6082 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6083 if (p1 == head || p2 == head)
6084 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6085 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6086 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6087 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6088 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6089 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6090 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6094 if (!playerdetail || skeleton.free == 3) {
6095 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6096 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6097 glMatrixMode(GL_MODELVIEW);
6099 if (p1 == abdomen || p2 == abdomen)
6100 glTranslatef(v0.x * proportionbody.x,
6101 v0.y * proportionbody.y,
6102 v0.z * proportionbody.z);
6103 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6104 glTranslatef(v0.x * proportionarms.x,
6105 v0.y * proportionarms.y,
6106 v0.z * proportionarms.z);
6107 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6108 glTranslatef(v0.x * proportionlegs.x,
6109 v0.y * proportionlegs.y,
6110 v0.z * proportionlegs.z);
6111 if (p1 == head || p2 == head)
6112 glTranslatef(v0.x * proportionhead.x,
6113 v0.y * proportionhead.y,
6114 v0.z * proportionhead.z);
6116 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6117 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6118 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6119 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6125 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6126 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6128 glMatrixMode(GL_MODELVIEW);
6132 glRotatef(tilt2, 1, 0, 0);
6134 glRotatef(tilt, 0, 0, 1);
6135 glTranslatef(mid.x, mid.y, mid.z);
6136 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6137 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6139 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6140 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6142 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6143 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6145 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6146 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6147 glMatrixMode(GL_MODELVIEW);
6149 if (p1 == abdomen || p2 == abdomen)
6150 glTranslatef(v0.x * proportionbody.x,
6151 v0.y * proportionbody.y,
6152 v0.z * proportionbody.z);
6153 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6154 glTranslatef(v0.x * proportionarms.x,
6155 v0.y * proportionarms.y,
6156 v0.z * proportionarms.z);
6157 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6158 glTranslatef(v0.x * proportionlegs.x,
6159 v0.y * proportionlegs.y,
6160 v0.z * proportionlegs.z);
6161 if (p1 == head || p2 == head)
6162 glTranslatef(v0.x * proportionhead.x,
6163 v0.y * proportionhead.y,
6164 v0.z * proportionhead.z);
6165 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6166 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6167 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6168 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6173 updatedelay = 1 + (float)(Random() % 100) / 1000;
6175 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6176 normalsupdatedelay = 1;
6177 if (playerdetail || skeleton.free == 3)
6178 skeleton.drawmodel.CalculateNormals(0);
6179 if (!playerdetail || skeleton.free == 3)
6180 skeleton.drawmodellow.CalculateNormals(0);
6181 if (skeleton.clothes)
6182 skeleton.drawmodelclothes.CalculateNormals(0);
6184 if (playerdetail || skeleton.free == 3)
6185 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6186 if (!playerdetail || skeleton.free == 3)
6187 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6188 if (skeleton.clothes) {
6189 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6194 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6195 if (updatedelaychange > -realmultiplier * 30)
6196 updatedelaychange = -realmultiplier * 30;
6197 if (updatedelaychange > -framemult * 4)
6198 updatedelaychange = -framemult * 4;
6199 if (skeleton.free == 1)
6200 updatedelaychange *= 6;
6202 updatedelaychange *= 8;
6203 updatedelay += updatedelaychange;
6205 glMatrixMode(GL_MODELVIEW);
6207 glTranslatef(coords.x, coords.y - .02, coords.z);
6208 if (!skeleton.free) {
6209 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6210 glRotatef(yaw, 0, 1, 0);
6214 glColor4f(.4, 1, .4, 1);
6215 glDisable(GL_LIGHTING);
6216 glDisable(GL_TEXTURE_2D);
6219 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6220 XYZ &v0 = skeleton.drawmodel.vertex[i];
6221 glVertex3f(v0.x, v0.y, v0.z);
6227 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6228 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6229 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6230 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6231 glVertex3f(v0.x, v0.y, v0.z);
6232 glVertex3f(v1.x, v1.y, v1.z);
6233 glVertex3f(v1.x, v1.y, v1.z);
6234 glVertex3f(v2.x, v2.y, v2.z);
6235 glVertex3f(v2.x, v2.y, v2.z);
6236 glVertex3f(v0.x, v0.y, v0.z);
6242 terrainlight = terrain.getLighting(coords.x, coords.z);
6243 distance = distsq(&viewer, &coords);
6244 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6248 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6249 if (terrainheight < 1)
6251 if (terrainheight > 1.7)
6252 terrainheight = 1.7;
6255 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6256 glDisable(GL_BLEND);
6257 glAlphaFunc(GL_GREATER, 0.0001);
6258 glEnable(GL_TEXTURE_2D);
6260 glDisable(GL_TEXTURE_2D);
6261 glColor4f(.7, .35, 0, .5);
6263 glEnable(GL_LIGHTING);
6266 if (tutoriallevel && id != 0) {
6267 glColor4f(.7, .7, .7, 0.6);
6269 glEnable(GL_LIGHTING);
6271 if (canattack && cananger)
6272 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6273 glDisable(GL_TEXTURE_2D);
6274 glColor4f(1, 0, 0, 0.8);
6276 glMatrixMode(GL_TEXTURE);
6278 glTranslatef(0, -smoketex, 0);
6279 glTranslatef(-smoketex, 0, 0);
6283 if ((tutoriallevel && id != 0))
6284 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6286 skeleton.drawmodel.draw();
6289 if (!playerdetail) {
6290 if ((tutoriallevel && id != 0))
6291 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6293 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6296 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6297 if (tutoriallevel && id != 0) {
6299 glMatrixMode(GL_MODELVIEW);
6300 glEnable(GL_TEXTURE_2D);
6301 glColor4f(.7, .7, .7, 0.6);
6303 glEnable(GL_LIGHTING);
6305 if (canattack && cananger)
6306 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6307 glDisable(GL_TEXTURE_2D);
6308 glColor4f(1, 0, 0, 0.8);
6310 glMatrixMode(GL_TEXTURE);
6312 glTranslatef(0, -smoketex * .6, 0);
6313 glTranslatef(smoketex * .6, 0, 0);
6316 if ((tutoriallevel && id != 0))
6317 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6319 skeleton.drawmodel.draw();
6322 if (!playerdetail) {
6323 if ((tutoriallevel && id != 0))
6324 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6326 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6331 if (tutoriallevel && id != 0) {
6333 glMatrixMode(GL_MODELVIEW);
6334 glEnable(GL_TEXTURE_2D);
6336 if (skeleton.clothes) {
6340 skeleton.drawmodelclothes.draw();
6342 skeleton.drawmodelclothes.drawimmediate();
6348 if (num_weapons > 0) {
6349 for (k = 0; k < num_weapons; k++) {
6351 if (weaponactive == k) {
6352 if (weapons[i].getType() != staff) {
6353 for (j = 0; j < skeleton.num_muscles; j++) {
6354 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6355 weaponattachmuscle = j;
6358 for (j = 0; j < skeleton.num_muscles; j++) {
6359 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) {
6360 weaponrotatemuscle = j;
6363 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6364 if (creature == wolftype)
6365 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6367 if (weapons[i].getType() == staff) {
6368 for (j = 0; j < skeleton.num_muscles; j++) {
6369 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6370 weaponattachmuscle = j;
6373 for (j = 0; j < skeleton.num_muscles; j++) {
6374 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) {
6375 weaponrotatemuscle = j;
6378 //weaponpoint=jointPos(rightwrist);
6379 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6380 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6381 XYZ tempnormthing, vec1, vec2;
6382 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6383 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6384 CrossProduct(&vec1, &vec2, &tempnormthing);
6385 Normalise(&tempnormthing);
6386 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6387 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6390 if (weaponactive != k && weaponstuck != k) {
6391 if (weapons[i].getType() == knife)
6392 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6393 if (weapons[i].getType() == sword)
6394 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6395 if (weapons[i].getType() == staff)
6396 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6397 for (j = 0; j < skeleton.num_muscles; j++) {
6398 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) {
6399 weaponrotatemuscle = j;
6403 if (weaponstuck == k) {
6404 if (weaponstuckwhere == 0)
6405 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6407 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6408 for (j = 0; j < skeleton.num_muscles; j++) {
6409 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) {
6410 weaponrotatemuscle = j;
6414 if (skeleton.free) {
6415 weapons[i].position = weaponpoint * scale + coords;
6416 weapons[i].bigrotation = 0;
6417 weapons[i].bigtilt = 0;
6418 weapons[i].bigtilt2 = 0;
6420 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;
6421 weapons[i].bigrotation = yaw;
6422 weapons[i].bigtilt = tilt;
6423 weapons[i].bigtilt2 = tilt2;
6425 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6426 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6427 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6428 if (weaponactive == k) {
6429 if (weapons[i].getType() == knife) {
6430 weapons[i].smallrotation = 180;
6431 weapons[i].smallrotation2 = 0;
6432 if (isCrouch() || wasCrouch()) {
6433 weapons[i].smallrotation2 = 20;
6435 if (animTarget == hurtidleanim) {
6436 weapons[i].smallrotation2 = 50;
6438 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6439 XYZ temppoint1, temppoint2;
6442 temppoint1 = jointPos(righthand);
6443 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6444 distance = findDistance(&temppoint1, &temppoint2);
6445 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6446 weapons[i].rotation2 *= 360 / 6.28;
6449 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6450 weapons[i].rotation1 *= 360 / 6.28;
6451 weapons[i].rotation3 = 0;
6452 weapons[i].smallrotation = -90;
6453 weapons[i].smallrotation2 = 0;
6454 if (temppoint1.x > temppoint2.x)
6455 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6457 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6458 XYZ temppoint1, temppoint2;
6461 temppoint1 = jointPos(righthand);
6462 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6463 distance = findDistance(&temppoint1, &temppoint2);
6464 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6465 weapons[i].rotation2 *= 360 / 6.28;
6468 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6469 weapons[i].rotation1 *= 360 / 6.28;
6470 weapons[i].rotation3 = 0;
6471 weapons[i].smallrotation = 90;
6472 weapons[i].smallrotation2 = 0;
6473 if (temppoint1.x > temppoint2.x)
6474 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6476 if (animTarget == knifethrowanim) {
6477 weapons[i].smallrotation = 90;
6478 //weapons[i].smallrotation2=-90;
6479 weapons[i].smallrotation2 = 0;
6480 weapons[i].rotation1 = 0;
6481 weapons[i].rotation2 = 0;
6482 weapons[i].rotation3 = 0;
6484 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6485 weapons[i].smallrotation = -90;
6486 weapons[i].rotation1 = 0;
6487 weapons[i].rotation2 = 0;
6488 weapons[i].rotation3 = 0;
6491 if (weapons[i].getType() == sword) {
6492 weapons[i].smallrotation = 0;
6493 weapons[i].smallrotation2 = 0;
6494 if (animTarget == knifethrowanim) {
6495 weapons[i].smallrotation = -90;
6496 weapons[i].smallrotation2 = 0;
6497 weapons[i].rotation1 = 0;
6498 weapons[i].rotation2 = 0;
6499 weapons[i].rotation3 = 0;
6501 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)) {
6502 XYZ temppoint1, temppoint2;
6505 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6506 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6507 distance = findDistance(&temppoint1, &temppoint2);
6508 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6509 weapons[i].rotation2 *= 360 / 6.28;
6512 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6513 weapons[i].rotation1 *= 360 / 6.28;
6514 weapons[i].rotation3 = 0;
6515 weapons[i].smallrotation = 90;
6516 weapons[i].smallrotation2 = 0;
6517 if (temppoint1.x > temppoint2.x)
6518 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6521 if (weapons[i].getType() == staff) {
6522 weapons[i].smallrotation = 100;
6523 weapons[i].smallrotation2 = 0;
6524 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6525 XYZ temppoint1, temppoint2;
6528 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6529 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6530 distance = findDistance(&temppoint1, &temppoint2);
6531 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6532 weapons[i].rotation2 *= 360 / 6.28;
6535 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6536 weapons[i].rotation1 *= 360 / 6.28;
6537 weapons[i].rotation3 = 0;
6538 weapons[i].smallrotation = 90;
6539 weapons[i].smallrotation2 = 0;
6540 if (temppoint1.x > temppoint2.x)
6541 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6545 if (weaponactive != k && weaponstuck != k) {
6546 if (weapons[i].getType() == knife) {
6547 weapons[i].smallrotation = -70;
6548 weapons[i].smallrotation2 = 10;
6550 if (weapons[i].getType() == sword) {
6551 weapons[i].smallrotation = -100;
6552 weapons[i].smallrotation2 = -8;
6554 if (weapons[i].getType() == staff) {
6555 weapons[i].smallrotation = -100;
6556 weapons[i].smallrotation2 = -8;
6559 if (weaponstuck == k) {
6560 if (weaponstuckwhere == 0)
6561 weapons[i].smallrotation = 180;
6563 weapons[i].smallrotation = 0;
6564 weapons[i].smallrotation2 = 10;
6573 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6575 if (animCurrent != animTarget)
6577 if (skeleton.free == 2)
6586 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6589 static float distance;
6590 static float olddistance;
6591 static int intersecting;
6592 static int firstintersecting;
6595 static XYZ start, end;
6596 static float slopethreshold = -.4;
6598 firstintersecting = -1;
6602 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6605 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6606 for (i = 0; i < 4; i++) {
6607 for (j = 0; j < model->TriangleNum; j++) {
6608 if (model->facenormals[j].y <= slopethreshold) {
6610 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)));
6611 if (distance < radius) {
6612 point = *p1 - model->facenormals[j] * distance;
6613 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]]))
6616 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6617 &model->vertex[model->Triangles[j].vertex[1]],
6620 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6621 &model->vertex[model->Triangles[j].vertex[2]],
6624 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6625 &model->vertex[model->Triangles[j].vertex[2]],
6628 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6632 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)) {
6633 p1->y = point.y + radius;
6634 if ((animTarget == jumpdownanim || isFlip())) {
6635 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6638 if (animTarget == jumpupanim) {
6640 animTarget = getIdle();
6647 pause_sound(whooshsound);
6648 OPENAL_SetVolume(channels[whooshsound], 0);
6651 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6654 animTarget = getLanding();
6655 emit_sound_at(landsound, coords, 128.);
6658 addEnvSound(coords);
6665 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6666 olddistance = distance;
6667 firstintersecting = j;
6672 for (j = 0; j < model->TriangleNum; j++) {
6673 if (model->facenormals[j].y > slopethreshold) {
6676 start.y -= radius / 4;
6677 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6678 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6679 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6680 distance = abs((model->facenormals[j].x * start.x)
6681 + (model->facenormals[j].y * start.y)
6682 + (model->facenormals[j].z * start.z)
6683 - ((model->facenormals[j].x * v0.x)
6684 + (model->facenormals[j].y * v0.y)
6685 + (model->facenormals[j].z * v0.z)));
6686 if (distance < radius * .5) {
6687 point = start - model->facenormals[j] * distance;
6688 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6691 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6693 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6695 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6697 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6698 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6700 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6701 if (findLengthfast(&start) < findLengthfast(&velocity))
6704 *p1 += model->facenormals[j] * (distance - radius * .5);
6707 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6708 olddistance = distance;
6709 firstintersecting = j;
6716 *p = DoRotation(*p, 0, *rotate, 0);
6719 *p1 = DoRotation(*p1, 0, *rotate, 0);
6721 return firstintersecting;
6724 void Person::takeWeapon(int weaponId)
6727 weapons[weaponId].owner = id;
6728 if (num_weapons > 0) {
6729 weaponids[num_weapons] = weaponids[0];
6732 weaponids[0] = weaponId;
6735 void Person::addClothes()
6737 if (numclothes > 0) {
6738 for (int i = 0; i < numclothes; i++) {
6745 bool Person::addClothes(const int& clothesId)
6748 const char* fileName = clothes[clothesId];
6750 GLubyte* array = &skeleton.skinText[0];
6754 bool opened = load_image(fileName, texture);
6759 float tintr = clothestintr[clothesId];
6760 float tintg = clothestintg[clothesId];
6761 float tintb = clothestintb[clothesId];
6763 if (tintr > 1) tintr = 1;
6764 if (tintg > 1) tintg = 1;
6765 if (tintb > 1) tintb = 1;
6767 if (tintr < 0) tintr = 0;
6768 if (tintg < 0) tintg = 0;
6769 if (tintb < 0) tintb = 0;
6771 int bytesPerPixel = texture.bpp / 8;
6775 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6776 if (bytesPerPixel == 3)
6778 else if ((i + 1) % 4 == 0)
6779 alphanum = texture.data[i];
6780 if ((i + 1) % 4 || bytesPerPixel == 3) {
6782 texture.data[i] *= tintr;
6784 texture.data[i] *= tintg;
6786 texture.data[i] *= tintb;
6787 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);