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 bool showpoints;
57 extern bool immediate;
58 extern int tutoriallevel;
59 extern float smoketex;
60 extern int tutorialstage;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern int indialogue;
70 extern bool gamestarted;
72 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
85 howactive(typeactive),
87 superruntoggle(false),
88 lastattack(0), lastattack2(0), lastattack3(0),
89 currentoffset(), targetoffset(), offset(),
121 rabbitkickenabled(false),
133 superpermanentdamage(0),
147 bleedx(0), bleedy(0),
151 headyaw(0), headpitch(0),
152 targetheadyaw(0), targetheadpitch(0),
163 normalsupdatedelay(0),
166 forwardkeydown(false),
167 forwardstogglekeydown(false),
172 jumptogglekeydown(false),
173 crouchkeydown(false),
174 crouchtogglekeydown(false),
176 drawtogglekeydown(false),
178 throwtogglekeydown(false),
179 attackkeydown(false),
184 crouchkeydowntime(0),
198 whichdirection(false),
199 whichdirectiondelay(0),
200 avoidsomething(false),
209 lefthandmorphness(0),
210 righthandmorphness(0),
214 targetlefthandmorphness(0),
215 targetrighthandmorphness(0),
216 targetheadmorphness(0),
217 targetchestmorphness(0),
218 targettailmorphness(0),
219 lefthandmorphstart(0), lefthandmorphend(0),
220 righthandmorphstart(0), righthandmorphend(0),
221 headmorphstart(0), headmorphend(0),
222 chestmorphstart(0), chestmorphend(0),
223 tailmorphstart(0), tailmorphend(0),
226 highreversaldelay(0),
229 creature(rabbittype),
276 finalpathfindpoint(0),
277 targetpathfindpoint(0),
278 lastpathfindpoint(0),
279 lastpathfindpoint2(0),
280 lastpathfindpoint3(0),
281 lastpathfindpoint4(0),
297 neckspurtparticledelay(0),
301 rabbitkickragdoll(false),
314 * GameTick/doPlayerCollisions
316 void Person::CheckKick()
319 && (animTarget == rabbitkickanim
321 && victim != this->shared_from_this()
323 && animCurrent == rabbitkickanim)
324 && distsq(&coords, &victim->coords) < 1.2
325 && !victim->skeleton.free))
328 if (animation[victim->animTarget].height != lowheight) {
329 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
330 XYZ relative = velocity;
332 Normalise(&relative);
336 if (tutoriallevel != 1)
337 emit_sound_at(heavyimpactsound, victim->coords);
339 for (int i = 0; i < victim->skeleton.num_joints; i++) {
340 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
343 victim->DoDamage(100 * damagemult / victim->protectionhigh);
349 animTarget = backflipanim;
351 velocity = facing * -10;
355 resume_stream(whooshsound);
357 award_bonus(id, cannon);
358 } else if (victim->isCrouch()) {
359 animTarget = rabbitkickreversedanim;
360 animCurrent = rabbitkickreversedanim;
361 victim->animCurrent = rabbitkickreversalanim;
362 victim->animTarget = rabbitkickreversalanim;
368 victim->oldcoords = victim->coords;
369 coords = victim->coords;
370 victim->targetyaw = targetyaw;
371 victim->victim = this->shared_from_this();
378 * GameTick/doPlayerCollisions - spread fire between players
379 * GameTick/doDebugKeys - press f to ignite
380 * Person::DoStuff - spread fire from lit campfires and bushes
382 void Person::CatchFire()
384 XYZ flatfacing, flatvelocity;
386 for (int i = 0; i < 10; i++) {
387 howmany = abs(Random() % (skeleton.num_joints));
389 flatvelocity = skeleton.joints[howmany].velocity;
390 flatfacing = skeleton.joints[howmany].position * scale + coords;
392 flatvelocity = velocity;
393 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
395 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
400 emit_sound_at(firestartsound, coords);
402 emit_stream_at(stream_firesound, coords);
410 * idle animation for this creature (depending on status)
412 int Person::getIdle()
414 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
416 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
417 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
418 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
419 victim->id < Person::players.size())) {
420 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
421 if (creature == rabbittype)
422 return fightidleanim;
423 if (creature == wolftype)
426 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
427 if (weapons[weaponids[weaponactive]].getType() == knife)
428 return knifefightidleanim;
429 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
430 return swordfightidlebothanim;
431 if (weapons[weaponids[weaponactive]].getType() == sword)
432 return swordfightidleanim;
433 if (weapons[weaponids[weaponactive]].getType() == staff)
434 return swordfightidleanim;
436 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
437 return fightsidestep;
439 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
441 if (howactive == typesitting) return sitanim;
442 if (howactive == typesittingwall) return sitwallanim;
443 if (howactive == typesleeping) return sleepanim;
444 if (howactive == typedead1) return dead1anim;
445 if (howactive == typedead2) return dead2anim;
446 if (howactive == typedead3) return dead3anim;
447 if (howactive == typedead4) return dead4anim;
448 if (creature == rabbittype) return bounceidleanim;
449 if (creature == wolftype) return wolfidle;
454 * crouch animation for this creature
456 int Person::getCrouch()
458 if (creature == rabbittype)
460 if (creature == wolftype)
461 return wolfcrouchanim;
466 * running animation for this creature (can be upright or all fours)
470 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
472 if (creature == wolftype && (!superruntoggle))
475 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
476 return rabbitrunninganim;
477 if (creature == wolftype && (superruntoggle))
478 return wolfrunninganim;
484 int Person::getStop()
486 if (creature == rabbittype)
488 if (creature == wolftype)
495 int Person::getLanding()
497 if (creature == rabbittype)
499 if (creature == wolftype)
506 int Person::getLandhard()
508 if (creature == rabbittype)
510 if (creature == wolftype)
511 return wolflandhardanim;
518 * Person::DoAnimations
521 SolidHitBonus(int playerid)
523 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
524 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
526 award_bonus(playerid, solidhit);
530 * spawns blood effects
532 void Person::DoBlood(float howmuch, int which)
534 // FIXME: should abstract out inputs
535 static int bleedxint, bleedyint;
537 if (bloodtoggle && tutoriallevel != 1) {
538 if (bleeding <= 0 && spurt) {
540 for (int i = 0; i < 3; i++) {
541 // emit blood particles
544 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
545 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
546 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
547 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
550 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
551 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
552 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
553 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
556 if (Random() % 2 == 0) // 50% chance
557 for (int i = 0; i < 3; i++) {
558 if (Random() % 2 != 0) {
559 // emit teeth particles
562 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
563 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
566 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
567 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
571 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
573 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
575 Sprite::setLastSpriteSpecial(3); // sets it to teeth
580 // FIXME: manipulating attributes
581 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
584 if (creature == rabbittype)
585 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) {
586 bleedxint = abs(Random() % 512);
587 bleedyint = abs(Random() % 512);
589 if (creature == wolftype)
590 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) {
591 bleedxint = abs(Random() % 512);
592 bleedyint = abs(Random() % 512);
596 bleedy /= realtexdetail;
597 bleedx /= realtexdetail;
598 direction = abs(Random() % 2) * 2 - 1;
607 * spawns big blood effects and ???
608 * modifies character's skin texture
610 void Person::DoBloodBig(float howmuch, int which)
612 static int bleedxint, bleedyint, i, j;
614 if (howmuch && id == 0)
617 if (tutoriallevel != 1 || id == 0)
618 if (aitype != playercontrolled && howmuch > 0) {
622 if (creature == wolftype) {
623 int i = abs(Random() % 2);
625 whichsound = snarlsound;
627 whichsound = snarl2sound;
629 if (creature == rabbittype) {
630 int i = abs(Random() % 2);
632 whichsound = rabbitpainsound;
633 if (i == 1 && howmuch >= 2)
634 whichsound = rabbitpain1sound;
637 if (whichsound != -1) {
638 emit_sound_at(whichsound, coords);
643 if (id == 0 && howmuch > 0) {
647 if (bloodtoggle && decals && tutoriallevel != 1) {
648 if (bleeding <= 0 && spurt) {
650 for (int i = 0; i < 3; i++) {
651 // emit blood particles
652 // FIXME: copypaste from above
655 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
656 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
657 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
658 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
661 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
662 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
663 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
664 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
669 // weird texture manipulation code follows.
670 // looks like this is painting blood onto the character's skin texture
671 // FIXME: surely there's a better way
673 int offsetx = 0, offsety = 0;
675 offsety = Random() % 40;
676 offsetx = abs(Random() % 60);
678 if (which == 190 || which == 185) {
679 offsety = Random() % 40;
680 offsetx = abs(Random() % 100) - 20;
683 offsety = Random() % 10;
684 offsetx = Random() % 10;
687 offsety = Random() % 20;
688 offsetx = Random() % 20;
690 if (which == 220 || which == 215) {
700 if (creature == rabbittype)
701 for (i = 0; i < 512; i++) {
702 for (j = 0; j < 512; j++) {
703 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
704 if (i < startx) startx = i;
705 if (j < starty) starty = j;
706 if (i > endx) endx = i;
707 if (j > endy) endy = j;
711 if (creature == wolftype)
712 for (i = 0; i < 512; i++) {
713 for (j = 0; j < 512; j++) {
714 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
715 if (i < startx) startx = i;
716 if (j < starty) starty = j;
717 if (i > endx) endx = i;
718 if (j > endy) endy = j;
728 if (startx < 0) startx = 0;
729 if (starty < 0) starty = 0;
730 if (endx > 512 - 1) endx = 512 - 1;
731 if (endy > 512 - 1) endy = 512 - 1;
732 if (endx < startx) endx = startx;
733 if (endy < starty) endy = starty;
735 startx /= realtexdetail;
736 starty /= realtexdetail;
737 endx /= realtexdetail;
738 endy /= realtexdetail;
740 int texdetailint = realtexdetail;
742 if (creature == rabbittype)
743 for (i = startx; i < endx; i++) {
744 for (j = starty; j < endy; j++) {
745 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) {
746 color = Random() % 85 + 170;
747 where = i * skeleton.skinsize * 3 + j * 3;
748 if (skeleton.skinText[where + 0] > color / 2)
749 skeleton.skinText[where + 0] = color / 2;
750 skeleton.skinText[where + 1] = 0;
751 skeleton.skinText[where + 2] = 0;
755 if (creature == wolftype)
756 for (i = startx; i < endx; i++) {
757 for (j = starty; j < endy; j++) {
758 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) {
759 color = Random() % 85 + 170;
760 where = i * skeleton.skinsize * 3 + j * 3;
761 if (skeleton.skinText[where + 0] > color / 2)
762 skeleton.skinText[where + 0] = color / 2;
763 skeleton.skinText[where + 1] = 0;
764 skeleton.skinText[where + 2] = 0;
768 skeleton.drawmodel.textureptr.bind();
773 if (creature == rabbittype)
774 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) {
775 bleedxint = abs(Random() % 512);
776 bleedyint = abs(Random() % 512);
778 if (creature == wolftype)
779 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) {
780 bleedxint = abs(Random() % 512);
781 bleedyint = abs(Random() % 512);
783 bleedy = bleedxint + offsetx;
784 bleedx = bleedyint + offsety;
785 bleedy /= realtexdetail;
786 bleedx /= realtexdetail;
791 if (bleedx > skeleton.skinsize - 1)
792 bleedx = skeleton.skinsize - 1;
793 if (bleedy > skeleton.skinsize - 1)
794 bleedy = skeleton.skinsize - 1;
795 direction = abs(Random() % 2) * 2 - 1;
798 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
799 deathbleeding += bleeding;
800 bloodloss += bleeding * 3;
802 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
803 if (abs(Random() % 2) == 0) {
804 aitype = gethelptype;
807 aitype = attacktypecutoff;
815 * similar to DoBloodBig
817 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
821 static XYZ startpoint, endpoint, colpoint, movepoint;
822 static float rotationpoint;
824 static XYZ p1, p2, p3, p0;
827 float coordsx, coordsy;
830 if (bloodtoggle && decals && tutoriallevel != 1) {
833 where = DoRotation(where, 0, -yaw, 0);
841 // ray testing for a tri in the character model
842 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
843 if (whichtri != -1) {
844 // low level geometry math
846 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
847 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
848 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
850 bary.x = distsq(&p0, &p1);
851 bary.y = distsq(&p0, &p2);
852 bary.z = distsq(&p0, &p3);
854 total = bary.x + bary.y + bary.z;
863 total = bary.x + bary.y + bary.z;
869 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
870 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
871 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
872 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
873 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
874 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
875 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;
876 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;
878 if (bleeding <= 0 && spurt) {
880 for (int i = 0; i < 3; i++) {
881 // emit blood particles
882 // FIXME: more copypaste code
885 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
886 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
887 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
888 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
891 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
892 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
893 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
894 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
899 // texture manipulation follows
901 int offsetx = 0, offsety = 0;
902 offsetx = (1 + coordsy) * 512 - 291;
903 offsety = coordsx * 512 - 437;
910 if (creature == rabbittype)
911 for (i = 0; i < 512; i++) {
912 for (j = 0; j < 512; j++) {
913 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
914 if (i < startx) startx = i;
915 if (j < starty) starty = j;
916 if (i > endx) endx = i;
917 if (j > endy) endy = j;
921 if (creature == wolftype)
922 for (i = 0; i < 512; i++) {
923 for (j = 0; j < 512; j++) {
924 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
925 if (i < startx) startx = i;
926 if (j < starty) starty = j;
927 if (i > endx) endx = i;
928 if (j > endy) endy = j;
937 if (startx < 0) startx = 0;
938 if (starty < 0) starty = 0;
939 if (endx > 512 - 1) endx = 512 - 1;
940 if (endy > 512 - 1) endy = 512 - 1;
941 if (endx < startx) endx = startx;
942 if (endy < starty) endy = starty;
944 startx /= realtexdetail;
945 starty /= realtexdetail;
946 endx /= realtexdetail;
947 endy /= realtexdetail;
949 int texdetailint = realtexdetail;
951 if (creature == rabbittype)
952 for (i = startx; i < endx; i++) {
953 for (j = starty; j < endy; j++) {
954 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) {
955 color = Random() % 85 + 170;
956 where = i * skeleton.skinsize * 3 + j * 3;
957 if (skeleton.skinText[where + 0] > color / 2)
958 skeleton.skinText[where + 0] = color / 2;
959 skeleton.skinText[where + 1] = 0;
960 skeleton.skinText[where + 2] = 0;
961 } 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) {
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;
971 if (creature == wolftype)
972 for (i = startx; i < endx; i++) {
973 for (j = starty; j < endy; j++) {
974 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) {
975 color = Random() % 85 + 170;
976 where = i * skeleton.skinsize * 3 + j * 3;
977 if (skeleton.skinText[where + 0] > color / 2)
978 skeleton.skinText[where + 0] = color / 2;
979 skeleton.skinText[where + 1] = 0;
980 skeleton.skinText[where + 2] = 0;
981 } 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) {
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;
991 skeleton.drawmodel.textureptr.bind();
994 bleedy = (1 + coordsy) * 512;
995 bleedx = coordsx * 512;
996 bleedy /= realtexdetail;
997 bleedx /= realtexdetail;
1002 if (bleedx > skeleton.skinsize - 1)
1003 bleedx = skeleton.skinsize - 1;
1004 if (bleedy > skeleton.skinsize - 1)
1005 bleedy = skeleton.skinsize - 1;
1006 direction = abs(Random() % 2) * 2 - 1;
1011 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1012 deathbleeding += bleeding;
1013 bloodloss += bleeding * 3;
1015 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1016 if (abs(Random() % 2) == 0) {
1017 aitype = gethelptype;
1020 aitype = attacktypecutoff;
1031 * guessing this performs a reversal
1033 void Person::Reverse()
1035 if (!((victim->aitype == playercontrolled
1037 || staggerdelay <= 0)
1038 && victim->animTarget != jumpupanim
1039 && victim->animTarget != jumpdownanim
1040 && (tutoriallevel != 1 || cananger)
1044 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1045 && (victim->id != 0 || difficulty >= 2)
1046 && (creature != wolftype || victim->creature == wolftype))
1049 if (animTarget == sweepanim) {
1050 animTarget = sweepreversedanim;
1051 animCurrent = sweepreversedanim;
1052 victim->animCurrent = sweepreversalanim;
1053 victim->animTarget = sweepreversalanim;
1055 if (animTarget == spinkickanim) {
1056 animTarget = spinkickreversedanim;
1057 animCurrent = spinkickreversedanim;
1058 victim->animCurrent = spinkickreversalanim;
1059 victim->animTarget = spinkickreversalanim;
1061 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1062 if (animTarget == rabbittacklinganim) {
1065 victim->frameCurrent = 6;
1066 victim->frameTarget = 7;
1068 animTarget = upunchreversedanim;
1069 animCurrent = upunchreversedanim;
1070 victim->animCurrent = upunchreversalanim;
1071 victim->animTarget = upunchreversalanim;
1073 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1074 if (victim->weaponactive != -1) {
1075 victim->throwtogglekeydown = 1;
1076 XYZ tempVelocity = victim->velocity * .2;
1077 if (tempVelocity.x == 0)
1078 tempVelocity.x = .1;
1079 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1080 victim->num_weapons--;
1081 if (victim->num_weapons) {
1082 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1083 if (victim->weaponstuck == victim->num_weapons)
1084 victim->weaponstuck = 0;
1087 victim->weaponactive = -1;
1088 for (unsigned j = 0; j < Person::players.size(); j++) {
1089 Person::players[j]->wentforweapon = 0;
1093 animTarget = staffhitreversedanim;
1094 animCurrent = staffhitreversedanim;
1095 victim->animCurrent = staffhitreversalanim;
1096 victim->animTarget = staffhitreversalanim;
1098 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1099 if (victim->weaponactive != -1) {
1100 victim->throwtogglekeydown = 1;
1101 XYZ tempVelocity = victim->velocity * .2;
1102 if (tempVelocity.x == 0)
1103 tempVelocity.x = .1;
1104 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1105 victim->num_weapons--;
1106 if (victim->num_weapons) {
1107 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1108 if (victim->weaponstuck == victim->num_weapons)
1109 victim->weaponstuck = 0;
1112 victim->weaponactive = -1;
1113 for (unsigned j = 0; j < Person::players.size(); j++) {
1114 Person::players[j]->wentforweapon = 0;
1117 animTarget = staffspinhitreversedanim;
1118 animCurrent = staffspinhitreversedanim;
1119 victim->animCurrent = staffspinhitreversalanim;
1120 victim->animTarget = staffspinhitreversalanim;
1122 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1123 if (victim->weaponactive != -1) {
1124 victim->throwtogglekeydown = 1;
1125 XYZ tempVelocity = victim->velocity * .2;
1126 if (tempVelocity.x == 0)
1127 tempVelocity.x = .1;
1128 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1129 victim->num_weapons--;
1130 if (victim->num_weapons) {
1131 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1132 if (victim->weaponstuck == victim->num_weapons)
1133 victim->weaponstuck = 0;
1136 victim->weaponactive = -1;
1137 for (unsigned j = 0; j < Person::players.size(); j++) {
1138 Person::players[j]->wentforweapon = 0;
1141 animTarget = swordslashreversedanim;
1142 animCurrent = swordslashreversedanim;
1143 victim->animCurrent = swordslashreversalanim;
1144 victim->animTarget = swordslashreversalanim;
1146 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1147 if (victim->weaponactive != -1) {
1148 victim->throwtogglekeydown = 1;
1149 XYZ tempVelocity = victim->velocity * .2;
1150 if (tempVelocity.x == 0)
1151 tempVelocity.x = .1;
1152 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1153 victim->num_weapons--;
1154 if (victim->num_weapons) {
1155 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1156 if (victim->weaponstuck == victim->num_weapons)
1157 victim->weaponstuck = 0;
1160 victim->weaponactive = -1;
1161 for (unsigned j = 0; j < Person::players.size(); j++) {
1162 Person::players[j]->wentforweapon = 0;
1165 animTarget = knifeslashreversedanim;
1166 animCurrent = knifeslashreversedanim;
1167 victim->animCurrent = knifeslashreversalanim;
1168 victim->animTarget = knifeslashreversalanim;
1170 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1171 victim->targettilt2 = targettilt2;
1172 victim->frameCurrent = frameCurrent;
1173 victim->frameTarget = frameTarget;
1174 victim->target = target;
1175 victim->velocity = 0;
1176 victim->oldcoords = victim->coords;
1177 victim->coords = coords;
1178 victim->targetyaw = targetyaw;
1179 victim->yaw = targetyaw;
1180 victim->victim = this->shared_from_this();
1182 if (animTarget == winduppunchanim) {
1183 animTarget = winduppunchblockedanim;
1184 victim->animTarget = blockhighleftanim;
1185 victim->frameTarget = 1;
1186 victim->target = .5;
1187 victim->victim = this->shared_from_this();
1188 victim->targetyaw = targetyaw + 180;
1190 if (animTarget == wolfslapanim) {
1191 animTarget = winduppunchblockedanim;
1192 victim->animTarget = blockhighleftanim;
1193 victim->frameTarget = 1;
1194 victim->target = .5;
1195 victim->victim = this->shared_from_this();
1196 victim->targetyaw = targetyaw + 180;
1198 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1199 animTarget = swordslashparriedanim;
1200 parriedrecently = .4;
1201 victim->parriedrecently = 0;
1202 victim->animTarget = swordslashparryanim;
1203 victim->frameTarget = 1;
1204 victim->target = .5;
1205 victim->victim = this->shared_from_this();
1206 victim->targetyaw = targetyaw + 180;
1208 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1209 if (victim->weaponactive != -1) {
1210 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1211 if (weapons[victim->weaponids[0]].getType() == staff)
1212 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1213 if (weapons[weaponids[0]].getType() == staff)
1214 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1215 emit_sound_at(swordstaffsound, victim->coords);
1217 emit_sound_at(metalhitsound, victim->coords);
1221 victim->Puff(righthand);
1223 victim->frameTarget = 0;
1224 victim->animTarget = staggerbackhighanim;
1225 victim->targetyaw = targetyaw + 180;
1227 aim = DoRotation(facing, 0, 90, 0) * 21;
1229 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1230 victim->num_weapons--;
1231 if (victim->num_weapons) {
1232 victim->weaponids[0] = victim->weaponids[num_weapons];
1233 if (victim->weaponstuck == victim->num_weapons)
1234 victim->weaponstuck = 0;
1236 victim->weaponactive = -1;
1237 for (unsigned i = 0; i < Person::players.size(); i++) {
1238 Person::players[i]->wentforweapon = 0;
1242 if (abs(Random() % 20) == 0) {
1243 if (weaponactive != -1) {
1244 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1245 if (weapons[victim->weaponids[0]].getType() == staff)
1246 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1247 if (weapons[weaponids[0]].getType() == staff)
1248 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1250 emit_sound_at(swordstaffsound, coords);
1252 emit_sound_at(metalhitsound, coords);
1260 animTarget = staggerbackhighanim;
1261 targetyaw = targetyaw + 180;
1263 aim = DoRotation(facing, 0, 90, 0) * 21;
1265 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1268 weaponids[0] = weaponids[num_weapons];
1269 if (weaponstuck == num_weapons)
1273 for (unsigned i = 0; i < Person::players.size(); i++) {
1274 Person::players[i]->wentforweapon = 0;
1281 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1282 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1283 victim->animTarget = dodgebackanim;
1284 victim->frameTarget = 0;
1288 rotatetarget = coords - victim->coords;
1289 Normalise(&rotatetarget);
1290 victim->targetyaw = -asin(0 - rotatetarget.x);
1291 victim->targetyaw *= 360 / 6.28;
1292 if (rotatetarget.z < 0)
1293 victim->targetyaw = 180 - victim->targetyaw;
1295 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1297 victim->lastattack3 = victim->lastattack2;
1298 victim->lastattack2 = victim->lastattack;
1299 victim->lastattack = victim->animTarget;
1301 victim->animTarget = sweepanim;
1302 victim->frameTarget = 0;
1306 rotatetarget = coords - victim->coords;
1307 Normalise(&rotatetarget);
1308 victim->targetyaw = -asin(0 - rotatetarget.x);
1309 victim->targetyaw *= 360 / 6.28;
1310 if (rotatetarget.z < 0)
1311 victim->targetyaw = 180 - victim->targetyaw;
1313 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1315 victim->lastattack3 = victim->lastattack2;
1316 victim->lastattack2 = victim->lastattack;
1317 victim->lastattack = victim->animTarget;
1322 victim->velocity = 0;
1324 if (aitype != playercontrolled)
1326 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1328 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1330 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1333 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1340 void Person::DoDamage(float howmuch)
1342 // subtract health (temporary?)
1343 if (tutoriallevel != 1)
1344 damage += howmuch / power;
1347 damagedealt += howmuch / power;
1349 damagetaken += howmuch / power;
1352 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1355 if (tutoriallevel != 1)
1356 permanentdamage += howmuch / 2 / power;
1357 if (tutoriallevel != 1)
1358 superpermanentdamage += howmuch / 4 / power;
1360 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1362 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1366 camerashake += howmuch / 100;
1367 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1368 blackout = damage / damagetolerance;
1373 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1374 aitype = attacktypecutoff;
1375 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1376 if (abs(Random() % 2) == 0) {
1377 aitype = gethelptype;
1380 aitype = attacktypecutoff;
1384 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1387 for (int i = 0; i < skeleton.num_joints; i++) {
1388 if (skeleton.free) {
1389 flatvelocity2 = skeleton.joints[i].velocity;
1390 flatfacing2 = skeleton.joints[i].position * scale + coords;
1392 flatvelocity2 = velocity;
1393 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1395 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1396 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1397 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1398 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1399 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1400 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1403 emit_sound_at(splattersound, coords);
1408 if (!dead && creature == wolftype) {
1409 award_bonus(0, Wolfbonus);
1416 if (tutoriallevel != 1 || id == 0)
1417 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1418 int whichsound = -1;
1420 if (creature == wolftype) {
1421 int i = abs(Random() % 2);
1423 whichsound = snarlsound;
1425 whichsound = snarl2sound;
1427 if (creature == rabbittype) {
1428 int i = abs(Random() % 2);
1430 whichsound = rabbitpainsound;
1431 if (i == 1 && damage > damagetolerance)
1432 whichsound = rabbitpain1sound;
1435 if (whichsound != -1) {
1436 emit_sound_at(whichsound, coords);
1437 addEnvSound(coords);
1444 * calculate/animate head facing direction?
1446 void Person::DoHead()
1448 static XYZ rotatearound;
1450 static float lookspeed = 500;
1452 if (!freeze && !winfreeze) {
1455 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1456 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1458 while (targetheadyaw > 180)targetheadyaw -= 360;
1459 while (targetheadyaw < -180)targetheadyaw += 360;
1461 if (targetheadyaw > 160)
1462 targetheadpitch = targetheadpitch * -1;
1463 if (targetheadyaw < -160)
1464 targetheadpitch = targetheadpitch * -1;
1465 if (targetheadyaw > 160)
1466 targetheadyaw = targetheadyaw - 180;
1467 if (targetheadyaw < -160)
1468 targetheadyaw = targetheadyaw + 180;
1470 if (targetheadpitch > 120)
1471 targetheadpitch = 120;
1472 if (targetheadpitch < -120)
1473 targetheadpitch = -120;
1474 if (targetheadyaw > 120)
1475 targetheadyaw = 120;
1476 if (targetheadyaw < -120)
1477 targetheadyaw = -120;
1480 targetheadpitch = 0;
1482 if (targetheadyaw > 80)
1484 if (targetheadyaw < -80)
1485 targetheadyaw = -80;
1486 if (targetheadpitch > 50)
1487 targetheadpitch = 50;
1488 if (targetheadpitch < -50)
1489 targetheadpitch = -50;
1492 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1493 headyaw = targetheadyaw;
1494 else if (headyaw > targetheadyaw) {
1495 headyaw -= multiplier * lookspeed;
1496 } else if (headyaw < targetheadyaw) {
1497 headyaw += multiplier * lookspeed;
1500 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1501 headpitch = targetheadpitch;
1502 else if (headpitch > targetheadpitch) {
1503 headpitch -= multiplier * lookspeed / 2;
1504 } else if (headpitch < targetheadpitch) {
1505 headpitch += multiplier * lookspeed / 2;
1508 rotatearound = jointPos(neck);
1509 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1513 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1514 facing = DoRotation(facing, headpitch * .4, 0, 0);
1515 facing = DoRotation(facing, 0, headyaw * .4, 0);
1518 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1519 facing = DoRotation(facing, headpitch * .8, 0, 0);
1520 facing = DoRotation(facing, 0, headyaw * .8, 0);
1523 if (animTarget == walkanim) {
1524 facing = DoRotation(facing, headpitch * .6, 0, 0);
1525 facing = DoRotation(facing, 0, headyaw * .6, 0);
1528 skeleton.specialforward[0] = facing;
1529 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1530 for (int i = 0; i < skeleton.num_muscles; i++) {
1531 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1532 skeleton.FindRotationMuscle(i, animTarget);
1539 * ragdolls character?
1541 void Person::RagDoll(bool checkcollision)
1546 if (!skeleton.free) {
1549 if (id == 0 && isFlip())
1556 facing = DoRotation(facing, 0, yaw, 0);
1558 skeleton.freetime = 0;
1560 skeleton.longdead = 0;
1563 skeleton.broken = 0;
1564 skeleton.spinny = 1;
1566 skeleton.freefall = 1;
1568 if (!isnormal(velocity.x)) velocity.x = 0;
1569 if (!isnormal(velocity.y)) velocity.y = 0;
1570 if (!isnormal(velocity.z)) velocity.z = 0;
1571 if (!isnormal(yaw)) yaw = 0;
1572 if (!isnormal(coords.x)) coords = 0;
1573 if (!isnormal(tilt)) tilt = 0;
1574 if (!isnormal(tilt2)) tilt2 = 0;
1576 for (int i = 0; i < skeleton.num_joints; i++) {
1577 skeleton.joints[i].delay = 0;
1578 skeleton.joints[i].locked = 0;
1579 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1580 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1581 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1582 skeleton.joints[i].position.y += .1;
1583 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1584 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1587 for (int i = 0; i < skeleton.num_joints; i++) {
1588 skeleton.joints[i].velocity = 0;
1589 skeleton.joints[i].velchange = 0;
1591 skeleton.DoConstraints(&coords, &scale);
1592 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1593 skeleton.DoConstraints(&coords, &scale);
1594 skeleton.DoConstraints(&coords, &scale);
1595 skeleton.DoConstraints(&coords, &scale);
1596 skeleton.DoConstraints(&coords, &scale);
1599 speed = animation[animTarget].speed[frameTarget] * 2;
1600 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1601 speed = animation[animCurrent].speed[frameCurrent] * 2;
1604 speed = transspeed * 2;
1608 for (int i = 0; i < skeleton.num_joints; i++) {
1609 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1610 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);
1612 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1613 change.x = (float)(Random() % 100) / 100;
1614 change.y = (float)(Random() % 100) / 100;
1615 change.z = (float)(Random() % 100) / 100;
1616 skeleton.joints[i].velocity += change;
1617 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1619 change.x = (float)(Random() % 100) / 100;
1620 change.y = (float)(Random() % 100) / 100;
1621 change.z = (float)(Random() % 100) / 100;
1622 skeleton.joints[i].velchange += change;
1623 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1626 if (checkcollision) {
1633 for (j = 0; j < skeleton.num_joints; j++) {
1634 average += skeleton.joints[j].position;
1638 coords += average * scale;
1639 for (j = 0; j < skeleton.num_joints; j++) {
1640 skeleton.joints[j].position -= average;
1643 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1644 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1645 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1646 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1647 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1650 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1651 coords.x = lowpoint.x;
1652 coords.z = lowpoint.z;
1661 for (int i = 0; i < skeleton.num_joints; i++) {
1662 velocity += skeleton.joints[i].velocity * scale;
1664 velocity /= skeleton.num_joints;
1667 if (Random() % 2 == 0) {
1668 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1669 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1670 weapons[weaponids[0]].velocity.x += .01;
1673 weaponids[0] = weaponids[num_weapons];
1674 if (weaponstuck == num_weapons)
1678 for (unsigned i = 0; i < Person::players.size(); i++) {
1679 Person::players[i]->wentforweapon = 0;
1684 animTarget = bounceidleanim;
1685 animCurrent = bounceidleanim;
1695 void Person::FootLand(int which, float opacity)
1697 static XYZ terrainlight;
1698 static XYZ footvel, footpoint;
1699 if (opacity >= 1 || skiddelay <= 0)
1703 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1705 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1706 //footpoint.y=coords.y;
1707 if (distsq(&footpoint, &viewer))
1708 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1709 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1710 footvel = velocity / 5;
1714 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1716 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1717 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1718 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1719 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1720 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1721 if (opacity >= 1 || detail == 2)
1723 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1724 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1725 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1726 footvel = velocity / 5;
1730 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1732 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1733 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1734 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1735 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1736 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1737 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1738 footvel = velocity / 5;
1742 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1744 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1745 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1746 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1747 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1748 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1749 if (opacity >= 1 || detail == 2)
1751 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1752 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1753 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1754 footvel = velocity / 5;
1758 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1760 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1761 //footpoint.y=coords.y;
1762 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1763 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1768 * make a puff effect at a body part (dust effect?)
1770 void Person::Puff(int whichlabel)
1772 static XYZ footvel, footpoint;
1775 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1776 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1780 * I think I added this in an attempt to clean up code
1782 void Person::setAnimation(int animation)
1784 animTarget = animation;
1793 void Person::DoAnimations()
1795 if (!skeleton.free) {
1796 static float oldtarget;
1798 if (isIdle() && animCurrent != getIdle())
1799 normalsupdatedelay = 0;
1801 if (animTarget == tempanim || animCurrent == tempanim) {
1802 animation[tempanim] = tempanimation;
1804 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1810 vel[0] = velocity.x;
1811 vel[1] = velocity.y;
1812 vel[2] = velocity.z;
1815 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1816 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1818 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1820 if (!crouchkeydown && velocity.y >= -15)
1823 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1828 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1830 if (normaldotproduct(targfacing, velocity) >= -.3)
1831 animTarget = flipanim;
1833 animTarget = backflipanim;
1834 crouchtogglekeydown = 1;
1842 if (animation[animTarget].attack != reversed)
1844 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1845 crouchtogglekeydown = 0;
1846 if (aitype == playercontrolled)
1849 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1852 crouchtogglekeydown = 1;
1856 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1858 normalsupdatedelay = 0;
1862 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1864 emit_sound_at(fireendsound, coords);
1865 pause_sound(stream_firesound);
1869 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1870 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1872 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1873 if (normaldotproduct(victim->facing, facing) > 0)
1874 victim->animTarget = rabbittackledbackanim;
1876 victim->animTarget = rabbittackledfrontanim;
1877 victim->frameTarget = 2;
1880 victim->targetyaw = yaw;
1881 if (victim->aitype == gethelptype)
1882 victim->DoDamage(victim->damagetolerance - victim->damage);
1883 //victim->DoDamage(30);
1884 if (creature == wolftype) {
1886 emit_sound_at(clawslicesound, victim->coords);
1888 victim->DoBloodBig(1 / victim->armorhead, 210);
1890 award_bonus(id, TackleBonus,
1891 victim->aitype == gethelptype ? 50 : 0);
1895 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1896 if (weapons[weaponids[0]].getType() == knife) {
1897 if (weaponactive == -1)
1899 else if (weaponactive == 0)
1902 if (weaponactive == -1) {
1903 emit_sound_at(knifesheathesound, coords);
1905 if (weaponactive != -1) {
1906 emit_sound_at(knifedrawsound, coords, 128);
1909 drawtogglekeydown = 1;
1912 if (tutoriallevel != 1 || id == 0)
1913 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1916 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1917 if (animation[animTarget].label[frameTarget] == 1)
1918 whichsound = footstepsound;
1920 whichsound = footstepsound2;
1921 if (animation[animTarget].label[frameTarget] == 1)
1923 if (animation[animTarget].label[frameTarget] == 2)
1925 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1931 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1932 if (animation[animTarget].label[frameTarget] == 1)
1933 whichsound = footstepsound3;
1935 whichsound = footstepsound4;
1939 if (animation[animTarget].label[frameTarget] == 1)
1940 whichsound = footstepsound3;
1942 whichsound = footstepsound4;
1944 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1945 if (animation[animTarget].attack != neutral) {
1946 unsigned r = abs(Random() % 3);
1948 whichsound = lowwhooshsound;
1950 whichsound = midwhooshsound;
1952 whichsound = highwhooshsound;
1954 if (animation[animTarget].attack == neutral)
1955 whichsound = movewhooshsound;
1956 } else if (animation[animTarget].label[frameTarget] == 4)
1957 whichsound = knifeswishsound;
1958 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1959 whichsound = landsound2;
1961 emit_sound_at(whichsound, coords, 256.);
1964 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1965 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
1966 addEnvSound(coords, 15);
1968 addEnvSound(coords, 6);
1972 if (animation[animTarget].label[frameTarget] == 3) {
1974 emit_sound_at(whichsound, coords, 128.);
1979 if (tutoriallevel != 1 || id == 0)
1980 if (speechdelay <= 0)
1981 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1982 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1983 int whichsound = -1;
1984 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1985 if (animation[animTarget].attack != neutral) {
1986 unsigned r = abs(Random() % 4);
1987 if (creature == rabbittype) {
1988 if (r == 0) whichsound = rabbitattacksound;
1989 if (r == 1) whichsound = rabbitattack2sound;
1990 if (r == 2) whichsound = rabbitattack3sound;
1991 if (r == 3) whichsound = rabbitattack4sound;
1993 if (creature == wolftype) {
1994 if (r == 0) whichsound = barksound;
1995 if (r == 1) whichsound = bark2sound;
1996 if (r == 2) whichsound = bark3sound;
1997 if (r == 3) whichsound = barkgrowlsound;
2003 if (whichsound != -1) {
2004 emit_sound_at(whichsound, coords);
2010 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2016 currentoffset = targetoffset;
2017 frameTarget = frameCurrent;
2018 animCurrent = animTarget;
2021 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2022 for (unsigned i = 0; i < weapons.size(); i++) {
2023 if (weapons[i].owner == -1)
2024 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2025 if (distsq(&coords, &weapons[i].position) >= 1) {
2026 if (weapons[i].getType() != staff) {
2027 emit_sound_at(knifedrawsound, coords, 128.);
2036 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2037 for (unsigned i = 0; i < weapons.size(); i++) {
2038 bool willwork = true;
2039 if (weapons[i].owner != -1)
2040 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2041 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2042 if (Person::players[weapons[i].owner]->num_weapons > 1)
2044 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2045 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2046 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2047 bool fleshstuck = false;
2048 if (weapons[i].owner != -1)
2049 if (victim->weaponstuck != -1) {
2050 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2055 emit_sound_at(fleshstabremovesound, coords, 128.);
2057 if (weapons[i].getType() != staff) {
2058 emit_sound_at(knifedrawsound, coords, 128.);
2061 if (weapons[i].owner != -1) {
2062 victim = Person::players[weapons[i].owner];
2063 if (victim->num_weapons == 1)
2064 victim->num_weapons = 0;
2066 victim->num_weapons = 1;
2068 //victim->weaponactive=-1;
2069 victim->skeleton.longdead = 0;
2070 victim->skeleton.free = 1;
2071 victim->skeleton.broken = 0;
2073 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2074 victim->skeleton.joints[j].velchange = 0;
2075 victim->skeleton.joints[j].locked = 0;
2081 Normalise(&relative);
2082 XYZ footvel, footpoint;
2084 footpoint = weapons[i].position;
2085 if (victim->weaponstuck != -1) {
2086 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2088 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2089 weapons[i].bloody = 2;
2090 weapons[i].blooddrip = 5;
2091 victim->weaponstuck = -1;
2094 if (victim->num_weapons > 0) {
2095 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2096 victim->weaponstuck = 0;
2097 if (victim->weaponids[0] == int(i))
2098 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2101 victim->jointVel(abdomen) += relative * 6;
2102 victim->jointVel(neck) += relative * 6;
2103 victim->jointVel(rightshoulder) += relative * 6;
2104 victim->jointVel(leftshoulder) += relative * 6;
2112 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2113 if (weaponactive == -1)
2115 else if (weaponactive == 0) {
2117 if (num_weapons == 2) {
2119 buffer = weaponids[0];
2120 weaponids[0] = weaponids[1];
2121 weaponids[1] = buffer;
2124 if (weaponactive == -1) {
2125 emit_sound_at(knifesheathesound, coords, 128.);
2127 if (weaponactive != -1) {
2128 emit_sound_at(knifedrawsound, coords, 128.);
2133 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2134 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2135 Normalise(&rotatetarget);
2136 targetyaw = -asin(0 - rotatetarget.x);
2137 targetyaw *= 360 / 6.28;
2138 if (rotatetarget.z < 0)
2139 targetyaw = 180 - targetyaw;
2141 if (animTarget == walljumprightkickanim)
2143 if (animTarget == walljumpleftkickanim)
2149 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2152 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2157 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2158 animTarget = rabbittackleanim;
2160 emit_sound_at(jumpsound, coords);
2168 targetloc = velocity;
2169 Normalise(&targetloc);
2170 targetloc += coords;
2171 for (unsigned i = 0; i < Person::players.size(); i++) {
2173 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2174 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2178 if (closestid != -1)
2179 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2181 victim = Person::players[closestid];
2182 coords = victim->coords;
2183 animCurrent = rabbittacklinganim;
2184 animTarget = rabbittacklinganim;
2188 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2189 rotatetarget = coords - victim->coords;
2190 Normalise(&rotatetarget);
2191 targetyaw = -asin(0 - rotatetarget.x);
2192 targetyaw *= 360 / 6.28;
2193 if (rotatetarget.z < 0)
2194 targetyaw = 180 - targetyaw;
2196 if (animTarget != rabbitrunninganim) {
2197 emit_sound_at(jumpsound, coords, 128.);
2203 float damagemult = 1 * power;
2204 if (creature == wolftype)
2205 damagemult = 2.5 * power;
2207 damagemult /= victim->damagetolerance / 200;
2209 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2210 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2211 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2215 if (Random() % 2 || creature == wolftype) {
2218 if (creature == wolftype)
2221 if (tutoriallevel != 1) {
2222 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2224 if (creature == wolftype) {
2225 emit_sound_at(clawslicesound, victim->coords, 128.);
2227 victim->DoBloodBig(2 / victim->armorhead, 175);
2231 relative = victim->coords - coords;
2233 Normalise(&relative);
2234 relative = DoRotation(relative, 0, -90, 0);
2235 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2236 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2238 victim->jointVel(head) += relative * damagemult * 200;
2241 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2247 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2248 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2252 if (Random() % 2 || creature == wolftype) {
2254 if (creature == wolftype)
2257 emit_sound_at(whooshhitsound, victim->coords);
2258 if (creature == wolftype) {
2259 emit_sound_at(clawslicesound, victim->coords, 128.);
2261 victim->DoBloodBig(2, 175);
2265 relative = victim->coords - coords;
2267 Normalise(&relative);
2269 Normalise(&relative);
2270 relative = DoRotation(relative, 0, 90, 0);
2271 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2272 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2274 victim->jointVel(head) += relative * damagemult * 100;
2277 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2281 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2282 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2288 if (tutoriallevel != 1) {
2289 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2291 if (creature == wolftype) {
2292 emit_sound_at(clawslicesound, victim->coords, 128.);
2294 victim->DoBloodBig(2 / victim->armorhead, 175);
2300 Normalise(&relative);
2301 relative = DoRotation(relative, 0, -90, 0);
2302 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2303 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2305 victim->jointVel(head) += relative * damagemult * 200;
2308 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2310 if (victim->damage > victim->damagetolerance)
2311 award_bonus(id, style);
2317 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2318 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2324 if (tutoriallevel != 1) {
2325 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2327 if (creature == wolftype) {
2328 emit_sound_at(clawslicesound, victim->coords, 128.);
2330 victim->DoBloodBig(2 / victim->armorhead, 175);
2336 Normalise(&relative);
2337 relative = DoRotation(relative, 0, 90, 0);
2338 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2339 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2341 victim->jointVel(head) += relative * damagemult * 200;
2344 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2346 if (victim->damage > victim->damagetolerance)
2347 award_bonus(id, style);
2353 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2354 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2362 emit_sound_at(whooshhitsound, victim->coords);
2365 relative = victim->coords - coords;
2367 Normalise(&relative);
2368 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2369 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2371 victim->jointVel(head) += relative * damagemult * 100;
2374 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2378 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2379 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2383 emit_sound_at(whooshhitsound, victim->coords, 128.);
2385 victim->skeleton.longdead = 0;
2386 victim->skeleton.free = 1;
2387 victim->skeleton.broken = 0;
2388 victim->skeleton.spinny = 1;
2390 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2391 victim->skeleton.joints[i].velchange = 0;
2392 victim->skeleton.joints[i].delay = 0;
2393 victim->skeleton.joints[i].locked = 0;
2394 //victim->skeleton.joints[i].velocity=0;
2400 Normalise(&relative);
2401 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2402 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2403 victim->skeleton.joints[i].position.y += relative.y * .3;
2404 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2405 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2407 victim->Puff(abdomen);
2408 victim->jointVel(abdomen).y = relative.y * 400;
2412 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2413 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2417 if (tutoriallevel != 1) {
2418 emit_sound_at(heavyimpactsound, coords, 128.);
2421 relative = victim->coords - coords;
2423 Normalise(&relative);
2424 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2425 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2427 victim->Puff(abdomen);
2428 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2432 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2433 victim->jointVel(abdomen) += relative * damagemult * 300;
2437 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2438 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2442 if (tutoriallevel != 1) {
2443 emit_sound_at(thudsound, coords);
2446 victim->skeleton.longdead = 0;
2447 victim->skeleton.free = 1;
2448 victim->skeleton.broken = 0;
2449 victim->skeleton.spinny = 1;
2451 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2452 victim->skeleton.joints[i].velchange = 0;
2453 //victim->skeleton.joints[i].delay=0;
2454 victim->skeleton.joints[i].locked = 0;
2457 relative = victim->coords - coords;
2458 Normalise(&relative);
2460 Normalise(&relative);
2461 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2462 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2467 victim->Puff(abdomen);
2468 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2469 victim->jointVel(abdomen) += relative * damagemult * 200;
2478 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2481 if (!victim->skeleton.free)
2485 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2486 emit_sound_at(knifesheathesound, coords, 128.);
2489 if (victim && hasvictim) {
2490 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2492 XYZ where, startpoint, endpoint, movepoint, colpoint;
2493 float rotationpoint;
2495 if (weapons[weaponids[weaponactive]].getType() == knife) {
2496 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2497 where -= victim->coords;
2498 if (!victim->skeleton.free)
2499 where = DoRotation(where, 0, -victim->yaw, 0);
2502 startpoint.y += 100;
2506 if (weapons[weaponids[weaponactive]].getType() == sword) {
2507 where = weapons[weaponids[weaponactive]].position;
2508 where -= victim->coords;
2509 if (!victim->skeleton.free)
2510 where = DoRotation(where, 0, -victim->yaw, 0);
2512 where = weapons[weaponids[weaponactive]].tippoint;
2513 where -= victim->coords;
2514 if (!victim->skeleton.free)
2515 where = DoRotation(where, 0, -victim->yaw, 0);
2518 if (weapons[weaponids[weaponactive]].getType() == staff) {
2519 where = weapons[weaponids[weaponactive]].position;
2520 where -= victim->coords;
2521 if (!victim->skeleton.free)
2522 where = DoRotation(where, 0, -victim->yaw, 0);
2524 where = weapons[weaponids[weaponactive]].tippoint;
2525 where -= victim->coords;
2526 if (!victim->skeleton.free)
2527 where = DoRotation(where, 0, -victim->yaw, 0);
2532 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2534 if (whichtri != -1) {
2535 if (victim->dead != 2) {
2536 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2538 award_bonus(id, FinishedBonus);
2541 weapons[weaponids[weaponactive]].bloody = 2;
2543 victim->skeleton.longdead = 0;
2544 victim->skeleton.free = 1;
2545 victim->skeleton.broken = 0;
2547 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2548 victim->skeleton.joints[i].velchange = 0;
2549 victim->skeleton.joints[i].locked = 0;
2550 //victim->skeleton.joints[i].velocity=0;
2552 emit_sound_at(fleshstabsound, coords, 128);
2555 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2556 weapons[weaponids[weaponactive]].blooddrip += 5;
2557 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2559 if (whichtri == -1) {
2561 emit_sound_at(knifesheathesound, coords, 128.);
2567 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2569 emit_sound_at(knifedrawsound, coords, 128);
2572 if (victim && hasvictim) {
2573 XYZ footvel, footpoint;
2575 emit_sound_at(fleshstabremovesound, coords, 128.);
2578 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2580 if (weapons[weaponids[weaponactive]].getType() == sword) {
2581 XYZ where, startpoint, endpoint, movepoint;
2582 float rotationpoint;
2585 where = weapons[weaponids[weaponactive]].position;
2586 where -= victim->coords;
2587 if (!victim->skeleton.free)
2588 where = DoRotation(where, 0, -victim->yaw, 0);
2590 where = weapons[weaponids[weaponactive]].tippoint;
2591 where -= victim->coords;
2592 if (!victim->skeleton.free)
2593 where = DoRotation(where, 0, -victim->yaw, 0);
2598 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2599 footpoint += victim->coords;
2601 if (whichtri == -1) {
2602 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2605 if (weapons[weaponids[weaponactive]].getType() == staff) {
2606 XYZ where, startpoint, endpoint, movepoint;
2607 float rotationpoint;
2610 where = weapons[weaponids[weaponactive]].position;
2611 where -= victim->coords;
2612 if (!victim->skeleton.free)
2613 where = DoRotation(where, 0, -victim->yaw, 0);
2615 where = weapons[weaponids[weaponactive]].tippoint;
2616 where -= victim->coords;
2617 if (!victim->skeleton.free)
2618 where = DoRotation(where, 0, -victim->yaw, 0);
2623 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2624 footpoint += victim->coords;
2626 if (whichtri == -1) {
2627 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2630 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2632 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2633 victim->skeleton.longdead = 0;
2634 victim->skeleton.free = 1;
2635 victim->skeleton.broken = 0;
2637 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2638 victim->skeleton.joints[i].velchange = 0;
2639 victim->skeleton.joints[i].locked = 0;
2640 //victim->skeleton.joints[i].velocity=0;
2646 Normalise(&relative);
2647 //victim->Puff(abdomen);
2649 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2651 if (victim->bloodloss < victim->damagetolerance) {
2652 victim->bloodloss += 1000;
2656 victim->jointVel(abdomen) += relative * damagemult * 20;
2660 if (!hasvictim && onterrain) {
2661 weapons[weaponids[weaponactive]].bloody = 0;
2662 weapons[weaponids[weaponactive]].blooddrip = 0;
2666 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2667 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2675 if (tutoriallevel != 1) {
2676 emit_sound_at(heavyimpactsound, victim->coords, 128);
2681 relative = victim->coords - coords;
2683 Normalise(&relative);
2684 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2685 victim->skeleton.joints[i].velocity = relative * 30;
2687 victim->jointVel(head) += relative * damagemult * 150;
2689 victim->frameTarget = 0;
2690 victim->animTarget = staggerbackhardanim;
2691 victim->targetyaw = targetyaw + 180;
2693 victim->stunned = 1;
2696 victim->Puff(abdomen);
2697 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2704 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2705 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2709 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2710 if (tutoriallevel != 1) {
2711 emit_sound_at(thudsound, victim->coords);
2713 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2714 if (tutoriallevel != 1) {
2715 emit_sound_at(whooshhitsound, victim->coords);
2718 if (tutoriallevel != 1) {
2719 emit_sound_at(heavyimpactsound, victim->coords);
2723 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2726 relative = victim->coords - coords;
2728 Normalise(&relative);
2730 Normalise(&relative);
2731 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2732 victim->skeleton.joints[i].velocity = relative * 5;
2734 victim->jointVel(abdomen) += relative * damagemult * 400;
2736 victim->frameTarget = 0;
2737 victim->animTarget = staggerbackhardanim;
2738 victim->targetyaw = targetyaw + 180;
2740 victim->stunned = 1;
2742 victim->Puff(abdomen);
2743 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2749 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2750 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2751 if (victim->id == 0)
2753 emit_sound_at(landsound2, victim->coords);
2759 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2760 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2761 if (victim->id == 0)
2764 if (weaponactive != -1) {
2765 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2766 if (weapons[victim->weaponids[0]].getType() == staff)
2767 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2768 if (weapons[weaponids[0]].getType() == staff)
2769 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2771 emit_sound_at(swordstaffsound, victim->coords);
2773 emit_sound_at(metalhitsound, victim->coords);
2781 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2782 if (weaponactive != -1) {
2785 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);
2787 weapons[weaponids[0]].thrown(aim * 50);
2790 weaponids[0] = weaponids[num_weapons];
2796 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2798 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2800 if (tutoriallevel != 1)
2801 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2803 award_bonus(id, Slicebonus);
2804 if (tutoriallevel != 1) {
2805 emit_sound_at(knifeslicesound, victim->coords);
2807 //victim->jointVel(abdomen)+=relative*damagemult*200;
2808 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2809 if (victim->id != 0 || difficulty == 2) {
2810 victim->frameTarget = 0;
2811 victim->animTarget = staggerbackhardanim;
2812 victim->targetyaw = targetyaw + 180;
2816 victim->lowreversaldelay = 0;
2817 victim->highreversaldelay = 0;
2818 if (aitype != playercontrolled)
2819 weaponmissdelay = .6;
2821 if (tutoriallevel != 1)
2822 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2823 weapons[weaponids[weaponactive]].bloody = 1;
2824 if (tutoriallevel != 1)
2825 weapons[weaponids[weaponactive]].blooddrip += 3;
2827 XYZ footvel, footpoint;
2829 if (skeleton.free) {
2830 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2832 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2834 if (tutoriallevel != 1) {
2836 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2837 footvel = DoRotation(facing, 0, 90, 0) * .8;
2839 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2840 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2841 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2842 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2844 if (tutoriallevel == 1) {
2845 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2847 victim->DoDamage(damagemult * 0);
2850 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2851 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2852 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2853 award_bonus(id, Slashbonus);
2855 if (tutoriallevel != 1) {
2856 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2857 victim->DoBloodBig(2 / victim->armorhigh, 190);
2859 victim->DoBloodBig(2 / victim->armorhigh, 185);
2860 victim->deathbleeding = 1;
2861 emit_sound_at(swordslicesound, victim->coords);
2863 //victim->jointVel(abdomen)+=relative*damagemult*200;
2864 if (tutoriallevel != 1) {
2865 victim->frameTarget = 0;
2866 victim->animTarget = staggerbackhardanim;
2867 victim->targetyaw = targetyaw + 180;
2871 if (tutoriallevel != 1) {
2872 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2873 weapons[weaponids[weaponactive]].bloody = 1;
2874 weapons[weaponids[weaponactive]].blooddrip += 3;
2876 float bloodlossamount;
2877 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2878 victim->bloodloss += bloodlossamount / victim->armorhigh;
2879 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2880 victim->DoDamage(damagemult * 0);
2882 XYZ footvel, footpoint;
2884 if (skeleton.free) {
2885 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2887 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2890 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2891 footvel = DoRotation(facing, 0, 90, 0) * .8;
2893 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2894 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2895 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2896 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2899 if (victim->weaponactive != -1) {
2900 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2901 if (weapons[victim->weaponids[0]].getType() == staff)
2902 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2903 if (weapons[weaponids[0]].getType() == staff)
2904 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2906 emit_sound_at(swordstaffsound, victim->coords);
2908 emit_sound_at(metalhitsound, victim->coords);
2914 victim->Puff(righthand);
2916 victim->frameTarget = 0;
2917 victim->animTarget = staggerbackhighanim;
2918 victim->targetyaw = targetyaw + 180;
2920 aim = DoRotation(facing, 0, 90, 0) * 21;
2922 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2923 victim->num_weapons--;
2924 if (victim->num_weapons) {
2925 victim->weaponids[0] = victim->weaponids[num_weapons];
2926 if (victim->weaponstuck == victim->num_weapons)
2927 victim->weaponstuck = 0;
2929 victim->weaponactive = -1;
2930 for (unsigned i = 0; i < Person::players.size(); i++) {
2931 Person::players[i]->wentforweapon = 0;
2938 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2939 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2940 if (tutoriallevel != 1) {
2941 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2945 if (Random() % 2 || creature == wolftype) {
2948 emit_sound_at(staffheadsound, victim->coords);
2952 relative = victim->coords - coords;
2954 Normalise(&relative);
2955 relative = DoRotation(relative, 0, 90, 0);
2957 Normalise(&relative);
2958 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2959 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2961 victim->jointVel(head) += relative * damagemult * 230;
2962 victim->jointVel(neck) += relative * damagemult * 230;
2965 if (tutoriallevel != 1) {
2966 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2968 award_bonus(id, solidhit, 30);
2973 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2974 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2975 if (tutoriallevel != 1) {
2976 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2980 if (Random() % 2 || creature == wolftype) {
2983 emit_sound_at(staffheadsound, victim->coords);
2987 relative = victim->coords - coords;
2989 Normalise(&relative);
2990 relative = DoRotation(relative, 0, -90, 0);
2991 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2992 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2994 victim->jointVel(head) += relative * damagemult * 220;
2995 victim->jointVel(neck) += relative * damagemult * 220;
2998 if (tutoriallevel != 1) {
2999 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3001 award_bonus(id, solidhit, 60);
3006 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3007 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3009 if (tutoriallevel != 1) {
3011 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3014 if (Random() % 2 || creature == wolftype) {
3017 emit_sound_at(staffbodysound, victim->coords);
3019 victim->skeleton.longdead = 0;
3020 victim->skeleton.free = 1;
3021 victim->skeleton.broken = 0;
3023 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3024 victim->skeleton.joints[i].velchange = 0;
3025 victim->skeleton.joints[i].locked = 0;
3026 //victim->skeleton.joints[i].velocity=0;
3032 /*relative=victim->coords-coords;
3034 Normalise(&relative);
3035 relative=DoRotation(relative,0,90,0);*/
3037 Normalise(&relative);
3038 if (!victim->dead) {
3039 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3040 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3043 victim->jointVel(abdomen) += relative * damagemult * 40;
3046 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3047 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3050 //victim->jointVel(abdomen)+=relative*damagemult*20;
3052 victim->Puff(abdomen);
3053 if (tutoriallevel != 1) {
3054 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3056 if (!victim->dead) {
3057 award_bonus(id, solidhit, 40);
3063 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3064 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3069 relative = victim->coords - coords;
3071 Normalise(&relative);
3075 if (animation[victim->animTarget].height == lowheight) {
3081 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3082 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3084 victim->jointVel(head) += relative * damagemult * 200;
3085 if (tutoriallevel != 1) {
3086 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3089 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3090 if (victim->howactive == typesleeping)
3091 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3092 if (creature == wolftype) {
3093 emit_sound_at(clawslicesound, victim->coords, 128.);
3095 victim->DoBloodBig(2 / victim->armorhead, 175);
3098 if (victim->damage >= victim->damagetolerance)
3100 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3101 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3103 victim->jointVel(abdomen) += relative * damagemult * 200;
3104 victim->frameTarget = 0;
3105 victim->animTarget = staggerbackhighanim;
3106 victim->targetyaw = targetyaw + 180;
3108 if (tutoriallevel != 1) {
3109 emit_sound_at(landsound2, victim->coords, 128.);
3111 victim->Puff(abdomen);
3112 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3113 if (creature == wolftype) {
3114 emit_sound_at(clawslicesound, victim->coords, 128.);
3116 victim->DoBloodBig(2 / victim->armorhigh, 170);
3123 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3124 if ((victim->animTarget != jumpupanim) &&
3125 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3126 (victim != this->shared_from_this())) {
3130 if (tutoriallevel != 1) {
3131 emit_sound_at(landsound2, victim->coords, 128.);
3134 relative = victim->coords - coords;
3136 Normalise(&relative);
3138 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3141 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3142 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3144 relative = DoRotation(relative, 0, -90, 0);
3146 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3147 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)
3148 victim->skeleton.joints[i].velocity = relative * 80;
3150 victim->Puff(rightankle);
3151 victim->Puff(leftankle);
3152 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3154 if (victim->damage >= victim->damagetolerance)
3156 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3157 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3159 relative = DoRotation(relative, 0, -90, 0);
3160 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3161 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)
3162 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3164 victim->jointVel(abdomen) += relative * damagemult * 200;
3165 victim->frameTarget = 0;
3166 victim->animTarget = staggerbackhighanim;
3167 victim->targetyaw = targetyaw + 180;
3169 if (tutoriallevel != 1) {
3170 emit_sound_at(landsound2, victim->coords, 128.);
3172 victim->Puff(abdomen);
3173 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3181 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3182 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3190 if (tutoriallevel != 1) {
3191 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3193 if (creature == wolftype) {
3194 emit_sound_at(clawslicesound, victim->coords, 128);
3196 victim->DoBloodBig(2 / victim->armorhigh, 170);
3200 relative = victim->coords - oldcoords;
3202 Normalise(&relative);
3203 //relative=DoRotation(relative,0,-90,0);
3204 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3205 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3207 victim->jointVel(abdomen) += relative * damagemult * 200;
3209 victim->Puff(abdomen);
3210 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3212 award_bonus(id, Reversal);
3215 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3216 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3217 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3218 takeWeapon(victim->weaponids[victim->weaponactive]);
3219 victim->num_weapons--;
3220 if (victim->num_weapons > 0) {
3221 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3223 victim->weaponactive = -1;
3228 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3236 emit_sound_at(whooshhitsound, victim->coords, 128.);
3239 relative = victim->coords - oldcoords;
3241 Normalise(&relative);
3242 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3243 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3245 victim->jointVel(abdomen) += relative * damagemult * 200;
3247 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3250 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3259 award_bonus(id, staffreversebonus);
3261 if (tutoriallevel != 1) {
3262 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3265 award_bonus(id, staffreversebonus); // Huh, again?
3268 relative = victim->coords - oldcoords;
3270 Normalise(&relative);
3271 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3272 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3274 victim->jointVel(abdomen) += relative * damagemult * 200;
3276 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3279 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3285 Normalise(&relative);
3287 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3288 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3290 victim->jointVel(lefthand) *= .1;
3291 victim->jointVel(leftwrist) *= .2;
3292 victim->jointVel(leftelbow) *= .5;
3293 victim->jointVel(leftshoulder) *= .7;
3294 victim->jointVel(righthand) *= .1;
3295 victim->jointVel(rightwrist) *= .2;
3296 victim->jointVel(rightelbow) *= .5;
3297 victim->jointVel(rightshoulder) *= .7;
3299 victim->Puff(abdomen);
3300 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3302 award_bonus(id, Reversal);
3306 if (weaponactive != -1 || creature == wolftype)
3308 if (creature == rabbittype && weaponactive != -1)
3309 if (weapons[weaponids[0]].getType() == staff)
3312 if (weaponactive != -1) {
3313 victim->DoBloodBig(2 / victim->armorhigh, 225);
3314 emit_sound_at(knifeslicesound, victim->coords);
3315 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3316 weapons[weaponids[weaponactive]].bloody = 1;
3317 weapons[weaponids[weaponactive]].blooddrip += 3;
3319 if (weaponactive == -1 && creature == wolftype) {
3321 emit_sound_at(clawslicesound, victim->coords, 128.);
3323 victim->DoBloodBig(2 / victim->armorhigh, 175);
3330 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3336 Normalise(&relative);
3338 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3339 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3341 victim->jointVel(lefthand) *= .1 - 1;
3342 victim->jointVel(leftwrist) *= .2 - 1;
3343 victim->jointVel(leftelbow) *= .5 - 1;
3344 victim->jointVel(leftshoulder) *= .7 - 1;
3345 victim->jointVel(righthand) *= .1 - 1;
3346 victim->jointVel(rightwrist) *= .2 - 1;
3347 victim->jointVel(rightelbow) *= .5 - 1;
3348 victim->jointVel(rightshoulder) *= .7 - 1;
3350 award_bonus(id, swordreversebonus);
3353 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3361 if (tutoriallevel != 1) {
3362 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3366 relative = victim->coords - oldcoords;
3368 Normalise(&relative);
3369 relative = DoRotation(relative, 0, -90, 0);
3370 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3371 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3373 victim->jointVel(abdomen) += relative * damagemult * 200;
3374 victim->Puff(abdomen);
3375 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3377 award_bonus(id, Reversal);
3380 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3383 victim->skeleton.spinny = 0;
3385 relative = facing * -1;
3387 Normalise(&relative);
3388 if (victim->id == 0)
3390 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3391 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3393 victim->damage = victim->damagetolerance;
3394 victim->permanentdamage = victim->damagetolerance - 1;
3397 if (weaponactive != -1 || creature == wolftype)
3399 if (creature == rabbittype && weaponactive != -1)
3400 if (weapons[weaponids[0]].getType() == staff)
3403 if (weaponactive != -1) {
3404 victim->DoBloodBig(200, 225);
3405 emit_sound_at(knifeslicesound, victim->coords);
3407 weapons[weaponids[weaponactive]].bloody = 2;
3408 weapons[weaponids[weaponactive]].blooddrip += 5;
3411 if (creature == wolftype && weaponactive == -1) {
3412 emit_sound_at(clawslicesound, victim->coords, 128.);
3414 victim->DoBloodBig(2, 175);
3417 award_bonus(id, spinecrusher);
3420 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3421 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3423 if (animTarget == knifefollowanim)
3424 victim->DoBloodBig(200, 210);
3425 if (animTarget == knifesneakattackanim) {
3426 XYZ footvel, footpoint;
3428 footpoint = weapons[weaponids[0]].tippoint;
3430 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3431 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3432 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3433 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3434 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3435 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3436 victim->DoBloodBig(200, 195);
3437 award_bonus(id, tracheotomy);
3439 if (animTarget == knifefollowanim) {
3440 award_bonus(id, Stabbonus);
3441 XYZ footvel, footpoint;
3443 footpoint = weapons[weaponids[0]].tippoint;
3445 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3446 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3447 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3448 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3449 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3450 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3453 victim->bloodloss += 10000;
3454 victim->velocity = 0;
3455 emit_sound_at(fleshstabsound, victim->coords);
3457 weapons[weaponids[weaponactive]].bloody = 2;
3458 weapons[weaponids[weaponactive]].blooddrip += 5;
3462 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3464 victim->velocity = 0;
3465 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3466 victim->skeleton.joints[i].velocity = 0;
3468 if (animTarget == knifefollowanim) {
3470 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3471 victim->skeleton.joints[i].velocity = 0;
3474 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3475 emit_sound_at(fleshstabremovesound, victim->coords);
3477 weapons[weaponids[weaponactive]].bloody = 2;
3478 weapons[weaponids[weaponactive]].blooddrip += 5;
3480 XYZ footvel, footpoint;
3482 footpoint = weapons[weaponids[0]].tippoint;
3484 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3485 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3486 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3487 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3488 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3489 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3493 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3494 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3495 award_bonus(id, backstab);
3499 XYZ footvel, footpoint;
3501 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3503 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3504 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3505 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3506 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3507 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3508 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3509 victim->DoBloodBig(200, 180);
3510 victim->DoBloodBig(200, 215);
3511 victim->bloodloss += 10000;
3512 victim->velocity = 0;
3513 emit_sound_at(fleshstabsound, victim->coords);
3515 weapons[weaponids[weaponactive]].bloody = 2;
3516 weapons[weaponids[weaponactive]].blooddrip += 5;
3520 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3522 victim->velocity = 0;
3523 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3524 victim->skeleton.joints[i].velocity = 0;
3526 if (weaponactive != -1) {
3527 emit_sound_at(fleshstabremovesound, victim->coords);
3529 weapons[weaponids[weaponactive]].bloody = 2;
3530 weapons[weaponids[weaponactive]].blooddrip += 5;
3532 XYZ footvel, footpoint;
3534 footpoint = weapons[weaponids[0]].tippoint;
3536 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3537 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3538 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3539 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3541 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3545 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3553 if (weaponactive == -1) {
3554 if (tutoriallevel != 1) {
3555 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3560 if (weaponactive != -1 || creature == wolftype)
3562 if (creature == rabbittype && weaponactive != -1)
3563 if (weapons[weaponids[0]].getType() == staff)
3566 if (weaponactive != -1) {
3567 victim->DoBloodBig(2 / victim->armorhead, 225);
3568 emit_sound_at(knifeslicesound, victim->coords);
3569 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3570 weapons[weaponids[weaponactive]].bloody = 1;
3571 weapons[weaponids[weaponactive]].blooddrip += 3;
3573 if (weaponactive == -1 && creature == wolftype) {
3574 emit_sound_at(clawslicesound, victim->coords, 128.);
3576 victim->DoBloodBig(2 / victim->armorhead, 175);
3580 award_bonus(id, Reversal);
3585 relative = facing * -1;
3587 Normalise(&relative);
3588 relative = DoRotation(relative, 0, 90, 0);
3590 Normalise(&relative);
3591 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3592 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3594 victim->jointVel(head) += relative * damagemult * 200;
3595 if (victim->damage < victim->damagetolerance - 100)
3596 victim->velocity = relative * 200;
3597 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3598 victim->velocity = 0;
3601 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3605 relative = facing * -1;
3607 Normalise(&relative);
3608 relative = DoRotation(relative, 0, 90, 0);
3610 Normalise(&relative);
3611 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3612 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3614 victim->jointVel(head) += relative * damagemult * 200;
3617 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3618 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3619 award_bonus(id, reverseko);
3625 if (frameTarget > animation[animCurrent].numframes - 1) {
3628 animTarget = getIdle();
3632 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3633 animTarget = rollanim;
3635 emit_sound_at(movewhooshsound, coords, 128.);
3637 if (animCurrent == staggerbackhighanim) {
3638 animTarget = getIdle();
3640 if (animCurrent == staggerbackhardanim) {
3641 animTarget = getIdle();
3643 if (animCurrent == removeknifeanim) {
3644 animTarget = getIdle();
3646 if (animCurrent == crouchremoveknifeanim) {
3647 animTarget = getCrouch();
3649 if (animCurrent == backhandspringanim) {
3650 animTarget = getIdle();
3652 if (animCurrent == dodgebackanim) {
3653 animTarget = getIdle();
3655 if (animCurrent == drawleftanim) {
3656 animTarget = getIdle();
3658 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3659 animTarget = getIdle();
3660 if (animCurrent == crouchdrawrightanim) {
3661 animTarget = getCrouch();
3663 if (weaponactive == -1)
3665 else if (weaponactive == 0) {
3667 if (num_weapons == 2) {
3669 buffer = weaponids[0];
3670 weaponids[0] = weaponids[1];
3671 weaponids[1] = buffer;
3675 if (weaponactive == -1) {
3676 emit_sound_at(knifesheathesound, coords, 128.);
3678 if (weaponactive != -1) {
3679 emit_sound_at(knifedrawsound, coords, 128.);
3682 if (animCurrent == rollanim) {
3683 animTarget = getCrouch();
3688 if (animTarget == walljumprightkickanim) {
3691 if (animTarget == walljumpleftkickanim) {
3694 animTarget = jumpdownanim;
3696 if (animCurrent == climbanim) {
3697 animTarget = getCrouch();
3699 coords += facing * .1;
3700 if (!isnormal(coords.x))
3711 if (animTarget == rabbitkickreversalanim) {
3712 animTarget = getCrouch();
3715 if (animTarget == jumpreversalanim) {
3716 animTarget = getCrouch();
3719 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3720 if (attackkeydown && animTarget != walljumpfrontanim) {
3722 float closestdist = -1;
3724 if (Person::players.size() > 1)
3725 for (unsigned i = 0; i < Person::players.size(); i++) {
3726 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3727 distance = distsq(&Person::players[i]->coords, &coords);
3728 if (closestdist == -1 || distance < closestdist) {
3729 closestdist = distance;
3734 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3735 victim = Person::players[closest];
3736 animTarget = walljumprightkickanim;
3738 XYZ rotatetarget = victim->coords - coords;
3739 Normalise(&rotatetarget);
3740 yaw = -asin(0 - rotatetarget.x);
3742 if (rotatetarget.z < 0)
3744 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3745 velocity = (victim->coords - coords) * 4;
3750 if (animTarget == walljumpbackanim) {
3751 animTarget = backflipanim;
3753 velocity = facing * -8;
3756 resume_stream(whooshsound);
3758 if (animTarget == walljumprightanim) {
3759 animTarget = rightflipanim;
3763 velocity = DoRotation(facing, 0, 30, 0) * -8;
3766 if (animTarget == walljumpfrontanim) {
3767 animTarget = frontflipanim;
3771 velocity = facing * 8;
3775 resume_stream(whooshsound);
3777 if (animTarget == walljumpleftanim) {
3778 if (attackkeydown) {
3780 float closestdist = -1;
3782 if (Person::players.size() > 1)
3783 for (unsigned i = 0; i < Person::players.size(); i++) {
3784 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3785 distance = distsq(&Person::players[i]->coords, &coords);
3786 if (closestdist == -1 || distance < closestdist) {
3787 closestdist = distance;
3792 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3793 victim = Person::players[closest];
3794 animTarget = walljumpleftkickanim;
3796 XYZ rotatetarget = victim->coords - coords;
3797 Normalise(&rotatetarget);
3798 yaw = -asin(0 - rotatetarget.x);
3800 if (rotatetarget.z < 0)
3802 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3803 velocity = (victim->coords - coords) * 4;
3808 if (animTarget != walljumpleftkickanim) {
3809 animTarget = leftflipanim;
3813 velocity = DoRotation(facing, 0, -30, 0) * -8;
3817 resume_stream(whooshsound);
3819 if (animTarget == sneakattackanim) {
3820 animCurrent = getCrouch();
3821 animTarget = getCrouch();
3828 transspeed = 1000000;
3829 targetheadyaw += 180;
3830 coords -= facing * .7;
3832 coords.y = terrain.getHeight(coords.x, coords.z);
3836 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3837 animTarget = getIdle();
3840 coords.y = terrain.getHeight(coords.x, coords.z);
3844 if (animCurrent == knifefollowanim) {
3845 animTarget = getIdle();
3848 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3849 float ycoords = oldcoords.y;
3850 animTarget = getStop();
3855 transspeed = 1000000;
3856 targetheadyaw += 180;
3857 if (!isnormal(coords.x))
3859 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3860 oldcoords = coords + facing * .5;
3861 else if (animCurrent == sweepreversalanim)
3862 oldcoords = coords + facing * 1.1;
3863 else if (animCurrent == upunchreversalanim) {
3864 oldcoords = coords + facing * 1.5;
3867 targetheadyaw += 180;
3870 } else if (animCurrent == knifeslashreversalanim) {
3871 oldcoords = coords + facing * .5;
3874 targetheadyaw += 90;
3877 } else if (animCurrent == staffspinhitreversalanim) {
3880 targetheadyaw += 180;
3885 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3887 oldcoords.y = ycoords;
3888 currentoffset = coords - oldcoords;
3894 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3899 if (animation[animTarget].attack == reversed) {
3901 if (animTarget == sweepreversedanim)
3903 animTarget = backhandspringanim;
3905 emit_sound_at(landsound, coords, 128);
3907 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3908 animTarget = rollanim;
3911 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3912 coords.y = oldcoords.y;
3914 if (animCurrent == knifeslashreversedanim) {
3915 animTarget = rollanim;
3920 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3921 coords.y = oldcoords.y;
3925 animTarget = jumpdownanim;
3928 animTarget = getIdle();
3930 animTarget = getIdle();
3931 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3932 animTarget = getIdle();
3934 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3935 coords.y = oldcoords.y;
3936 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3937 targetoffset.y = coords.y;
3939 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3940 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3941 currentoffset.y -= (coords.y - targetoffset.y);
3942 coords.y = targetoffset.y;
3944 normalsupdatedelay = 0;
3946 if (animCurrent == upunchanim) {
3947 animTarget = getStop();
3948 normalsupdatedelay = 0;
3951 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3955 if (num_weapons > 0)
3956 if (weapons[0].getType() == staff)
3962 rabbitkickragdoll = 1;
3964 if (animCurrent == rabbitkickreversedanim) {
3970 skeleton.spinny = 0;
3971 SolidHitBonus(!id); // FIXME: tricky id
3975 animTarget = rollanim;
3978 pause_sound(whooshsound);
3982 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3986 skeleton.spinny = 0;
3988 if (animCurrent == jumpreversedanim) {
3994 skeleton.spinny = 0;
3995 SolidHitBonus(!id); // FIXME: tricky id
3999 animTarget = rollanim;
4000 coords += facing * 2;
4002 pause_sound(whooshsound);
4007 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) {
4008 animTarget = getupfromfrontanim;
4010 } else if (animation[animCurrent].attack == normalattack) {
4011 animTarget = getIdle();
4014 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4015 animTarget = blockhighleftstrikeanim;
4017 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4018 animTarget = getIdle();
4021 if (animCurrent == spinkickanim && victim->skeleton.free) {
4022 if (creature == rabbittype)
4023 animTarget = fightidleanim;
4028 if (isIdle() && !wasIdle())
4029 normalsupdatedelay = 0;
4031 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4032 animTarget = jumpdownanim;
4035 if (!skeleton.free) {
4037 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4038 if (!isRun() || !wasRun()) {
4039 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4040 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4041 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4042 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4044 if (isRun() && wasRun()) {
4046 tempspeed = velspeed;
4047 if (tempspeed < 10 * speedmult)
4048 tempspeed = 10 * speedmult;
4049 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4051 } else if (transspeed)
4052 target += multiplier * transspeed * speed * 2;
4054 if (!isRun() || !wasRun()) {
4055 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4056 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4057 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4058 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4062 if (animCurrent != animTarget)
4063 target = (target + oldtarget) / 2;
4066 frameCurrent = frameTarget;
4070 rot = targetrot * target;
4071 yaw += rot - oldrot;
4077 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4079 for (int i = 0; i < skeleton.num_joints; i++) {
4080 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4083 skeleton.FindForwards();
4085 for (int i = 0; i < skeleton.num_muscles; i++) {
4086 if (skeleton.muscles[i].visible) {
4087 skeleton.FindRotationMuscle(i, animTarget);
4090 for (int i = 0; i < skeleton.num_muscles; i++) {
4091 if (skeleton.muscles[i].visible) {
4092 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4093 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4094 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4095 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4096 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4097 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4102 for (int i = 0; i < skeleton.num_joints; i++) {
4103 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4106 skeleton.FindForwards();
4108 for (int i = 0; i < skeleton.num_muscles; i++) {
4109 if (skeleton.muscles[i].visible) {
4110 skeleton.FindRotationMuscle(i, animTarget);
4113 for (int i = 0; i < skeleton.num_muscles; i++) {
4114 if (skeleton.muscles[i].visible) {
4115 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4116 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4117 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4118 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4119 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4120 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4121 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4122 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4123 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4124 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4125 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4126 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4130 if (frameCurrent >= animation[animCurrent].numframes)
4131 frameCurrent = animation[animCurrent].numframes - 1;
4133 oldanimCurrent = animCurrent;
4134 oldanimTarget = animTarget;
4135 oldframeTarget = frameTarget;
4136 oldframeCurrent = frameCurrent;
4138 for (int i = 0; i < skeleton.num_joints; i++) {
4139 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4140 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4142 offset = currentoffset * (1 - target) + targetoffset * target;
4143 for (int i = 0; i < skeleton.num_muscles; i++) {
4144 if (skeleton.muscles[i].visible) {
4145 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4146 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4147 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4152 if (isLanding() && landhard) {
4155 animTarget = getLandhard();
4168 void Person::DoStuff()
4170 static XYZ terrainnormal;
4171 static XYZ flatfacing;
4172 static XYZ flatvelocity;
4173 static float flatvelspeed;
4177 static int bloodsize;
4178 static int startx, starty, endx, endy;
4179 static GLubyte color;
4180 static XYZ bloodvel;
4182 onfiredelay -= multiplier;
4183 if (onfiredelay < 0 && onfire) {
4184 if (Random() % 2 == 0) {
4190 crouchkeydowntime += multiplier;
4192 crouchkeydowntime = 0;
4193 jumpkeydowntime += multiplier;
4194 if (!jumpkeydown && skeleton.free)
4195 jumpkeydowntime = 0;
4197 if (hostile || damage > 0 || bloodloss > 0)
4200 if (isIdle() || isRun())
4203 if (num_weapons == 1 && weaponactive != -1)
4207 blooddimamount -= multiplier * .3;
4208 speechdelay -= multiplier;
4209 texupdatedelay -= multiplier;
4210 interestdelay -= multiplier;
4211 flamedelay -= multiplier;
4212 parriedrecently -= multiplier;
4214 victim = this->shared_from_this();
4219 speed = 1.1 * speedmult;
4221 speed = 1.0 * speedmult;
4223 rabbitkickragdoll = 0;
4227 if (id != 0 && (creature == rabbittype || difficulty != 2))
4229 if (id != 0 && creature == wolftype && difficulty == 2) {
4231 if (aitype != passivetype) {
4233 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) {
4239 if (animTarget == wolfrunninganim && !superruntoggle) {
4240 animTarget = getRun();
4244 if (weaponactive == -1 && num_weapons > 0) {
4245 if (weapons[weaponids[0]].getType() == staff) {
4251 burnt += multiplier;
4255 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4257 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4263 vel[0] = velocity.x;
4264 vel[1] = velocity.y;
4265 vel[2] = velocity.z;
4268 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4269 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4273 while (flamedelay < 0 && onfire) {
4275 howmany = abs(Random() % (skeleton.num_joints));
4276 if (skeleton.free) {
4277 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4278 flatfacing = skeleton.joints[howmany].position * scale + coords;
4280 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4281 flatvelocity = (coords - oldcoords) / multiplier / 2;
4283 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4286 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4288 howmany = abs(Random() % (skeleton.num_joints));
4289 if (skeleton.free) {
4290 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4291 flatfacing = skeleton.joints[howmany].position * scale + coords;
4293 flatvelocity = (coords - oldcoords) / multiplier / 2;
4294 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4296 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4300 bleeding -= multiplier * .3;
4301 if (bloodtoggle == 2) {
4302 skeleton.drawmodel.textureptr.bind();
4303 if ((bleeding <= 0) && (detail != 2))
4308 if (neckspurtamount > 0) {
4309 neckspurtamount -= multiplier;
4310 neckspurtdelay -= multiplier * 3;
4311 neckspurtparticledelay -= multiplier * 3;
4312 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4315 if (skeleton.free) {
4316 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4317 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4318 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4320 bloodvel.z = 5 * neckspurtamount;
4321 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4322 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4323 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4325 neckspurtparticledelay = .05;
4327 if (neckspurtdelay < 0) {
4332 if (deathbleeding > 0 && dead != 2) {
4333 if (deathbleeding < 5)
4334 bleeddelay -= deathbleeding * multiplier / 4;
4336 bleeddelay -= 5 * multiplier / 4;
4337 if (bleeddelay < 0 && bloodtoggle) {
4342 if (skeleton.free) {
4343 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4344 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4346 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4347 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4351 bloodloss += deathbleeding * multiplier * 80;
4352 deathbleeding -= multiplier * 1.6;
4353 if (deathbleeding < 0)
4355 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4356 if (weaponactive != -1) {
4357 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4358 weapons[weaponids[0]].velocity.x += .01;
4361 weaponids[0] = weaponids[num_weapons];
4362 if (weaponstuck == num_weapons)
4366 for (unsigned i = 0; i < Person::players.size(); i++) {
4367 Person::players[i]->wentforweapon = 0;
4375 if (!dead && creature == wolftype) {
4376 award_bonus(0, Wolfbonus);
4379 if (animTarget == knifefollowedanim && !skeleton.free) {
4380 for (int i = 0; i < skeleton.num_joints; i++) {
4381 skeleton.joints[i].velocity = 0;
4382 skeleton.joints[i].velocity.y = -2;
4385 if (id != 0 && unconscioustime > .1) {
4393 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4394 texupdatedelay = .12;
4396 bloodsize = 5 - realtexdetail;
4400 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4401 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4402 endx = startx + bloodsize;
4403 endy = starty + bloodsize;
4413 if (endx > skeleton.skinsize - 1) {
4414 endx = skeleton.skinsize - 1;
4417 if (endy > skeleton.skinsize - 1) {
4418 endy = skeleton.skinsize - 1;
4426 for (i = startx; i < endx; i++) {
4427 for (j = starty; j < endy; j++) {
4428 if (Random() % 2 == 0) {
4429 color = Random() % 85 + 170;
4430 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4431 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4432 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4433 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4438 skeleton.drawmodel.textureptr.bind();
4442 if (skeleton.free) {
4443 bleedx += 4 * direction / realtexdetail;
4445 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4447 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4449 bleedy -= 4 / realtexdetail;
4451 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4453 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4457 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4458 righthandmorphness = targetrighthandmorphness;
4459 righthandmorphstart = righthandmorphend;
4460 } else if (righthandmorphness > targetrighthandmorphness) {
4461 righthandmorphness -= multiplier * 4;
4462 } else if (righthandmorphness < targetrighthandmorphness) {
4463 righthandmorphness += multiplier * 4;
4466 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4467 lefthandmorphness = targetlefthandmorphness;
4468 lefthandmorphstart = lefthandmorphend;
4469 } else if (lefthandmorphness > targetlefthandmorphness) {
4470 lefthandmorphness -= multiplier * 4;
4471 } else if (lefthandmorphness < targetlefthandmorphness) {
4472 lefthandmorphness += multiplier * 4;
4475 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4476 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4477 tailmorphness = targettailmorphness;
4478 tailmorphstart = tailmorphend;
4479 } else if (tailmorphness > targettailmorphness) {
4480 tailmorphness -= multiplier * 10;
4481 } else if (tailmorphness < targettailmorphness) {
4482 tailmorphness += multiplier * 10;
4486 if (creature == wolftype) {
4487 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4488 tailmorphness = targettailmorphness;
4489 tailmorphstart = tailmorphend;
4490 } else if (tailmorphness > targettailmorphness) {
4491 tailmorphness -= multiplier * 2;
4492 } else if (tailmorphness < targettailmorphness) {
4493 tailmorphness += multiplier * 2;
4497 if (headmorphend == 3 || headmorphstart == 3) {
4498 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4499 headmorphness = targetheadmorphness;
4500 headmorphstart = headmorphend;
4501 } else if (headmorphness > targetheadmorphness) {
4502 headmorphness -= multiplier * 7;
4503 } else if (headmorphness < targetheadmorphness) {
4504 headmorphness += multiplier * 7;
4506 } else if (headmorphend == 5 || headmorphstart == 5) {
4507 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4508 headmorphness = targetheadmorphness;
4509 headmorphstart = headmorphend;
4510 } else if (headmorphness > targetheadmorphness) {
4511 headmorphness -= multiplier * 10;
4512 } else if (headmorphness < targetheadmorphness) {
4513 headmorphness += multiplier * 10;
4516 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4517 headmorphness = targetheadmorphness;
4518 headmorphstart = headmorphend;
4519 } else if (headmorphness > targetheadmorphness) {
4520 headmorphness -= multiplier * 4;
4521 } else if (headmorphness < targetheadmorphness) {
4522 headmorphness += multiplier * 4;
4526 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4527 chestmorphness = targetchestmorphness;
4528 chestmorphstart = chestmorphend;
4529 } else if (chestmorphness > targetchestmorphness) {
4530 chestmorphness -= multiplier;
4531 } else if (chestmorphness < targetchestmorphness) {
4532 chestmorphness += multiplier;
4535 if (dead != 2 && howactive <= typesleeping) {
4536 if (chestmorphstart == 0 && chestmorphend == 0) {
4538 targetchestmorphness = 1;
4541 if (chestmorphstart != 0 && chestmorphend != 0) {
4543 targetchestmorphness = 1;
4545 if (environment == snowyenvironment) {
4548 if (skeleton.free) {
4549 footvel = skeleton.specialforward[0] * -1;
4550 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4552 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4553 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4555 if (animTarget == sleepanim)
4556 footvel = DoRotation(footvel, 0, 90, 0);
4557 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4561 if (!dead && howactive < typesleeping) {
4562 blinkdelay -= multiplier * 2;
4563 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4565 targetheadmorphness = 1;
4567 blinkdelay = (float)(abs(Random() % 40)) / 5;
4569 if (headmorphstart == 3 && headmorphend == 3) {
4571 targetheadmorphness = 1;
4576 twitchdelay -= multiplier * 1.5;
4577 if (animTarget != hurtidleanim) {
4578 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4580 targetheadmorphness = 1;
4582 twitchdelay = (float)(abs(Random() % 40)) / 5;
4584 if (headmorphstart == 5 && headmorphend == 5) {
4586 targetheadmorphness = 1;
4590 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4591 twitchdelay3 -= multiplier * 1;
4592 if (Random() % 2 == 0) {
4593 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4594 righthandmorphness = 0;
4595 targetrighthandmorphness = 1;
4596 righthandmorphend = 1;
4597 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4599 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4600 righthandmorphness = 0;
4601 targetrighthandmorphness = 1;
4602 righthandmorphend = 0;
4605 if (Random() % 2 == 0) {
4606 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4607 lefthandmorphness = 0;
4608 targetlefthandmorphness = 1;
4609 lefthandmorphend = 1;
4610 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4612 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4613 lefthandmorphness = 0;
4614 targetlefthandmorphness = 1;
4615 lefthandmorphend = 0;
4621 if (creature == rabbittype) {
4622 if (howactive < typesleeping)
4623 twitchdelay2 -= multiplier * 1.5;
4625 twitchdelay2 -= multiplier * 0.5;
4626 if (howactive <= typesleeping) {
4627 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4629 targettailmorphness = 1;
4631 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4633 if (tailmorphstart == 1 && tailmorphend == 1) {
4635 targettailmorphness = 1;
4638 if (tailmorphstart == 2 && tailmorphend == 2) {
4640 targettailmorphness = 1;
4647 if (creature == wolftype) {
4648 twitchdelay2 -= multiplier * 1.5;
4649 if (tailmorphend != 0)
4650 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4652 targettailmorphness = 1;
4656 if (tailmorphend != 5)
4657 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4659 targettailmorphness = 1;
4663 if (twitchdelay2 <= 0) {
4664 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4666 targettailmorphness = 1;
4669 if (tailmorphstart == 1 && tailmorphend == 1) {
4671 targettailmorphness = 1;
4674 if (tailmorphstart == 2 && tailmorphend == 2) {
4676 targettailmorphness = 1;
4679 if (tailmorphstart == 3 && tailmorphend == 3) {
4681 targettailmorphness = 1;
4684 if (tailmorphstart == 4 && tailmorphend == 4) {
4686 targettailmorphness = 1;
4693 unconscioustime = 0;
4695 if (dead == 1 || howactive == typesleeping) {
4696 unconscioustime += multiplier;
4697 //If unconscious, close eyes and mouth
4698 if (righthandmorphend != 0)
4699 righthandmorphness = 0;
4700 righthandmorphend = 0;
4701 targetrighthandmorphness = 1;
4703 if (lefthandmorphend != 0)
4704 lefthandmorphness = 0;
4705 lefthandmorphend = 0;
4706 targetlefthandmorphness = 1;
4708 if (headmorphend != 3 && headmorphend != 5)
4711 targetheadmorphness = 1;
4715 if (howactive > typesleeping) {
4718 if (bloodtoggle && !bled) {
4719 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4721 if (bloodtoggle && !bled)
4722 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4723 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4724 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4728 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4733 if (dead == 2 || howactive > typesleeping) {
4734 //If dead, open mouth and hands
4735 if (righthandmorphend != 0)
4736 righthandmorphness = 0;
4737 righthandmorphend = 0;
4738 targetrighthandmorphness = 1;
4740 if (lefthandmorphend != 0)
4741 lefthandmorphness = 0;
4742 lefthandmorphend = 0;
4743 targetlefthandmorphness = 1;
4745 if (headmorphend != 2)
4748 targetheadmorphness = 1;
4751 if (stunned > 0 && !dead && headmorphend != 2) {
4752 if (headmorphend != 4)
4755 targetheadmorphness = 1;
4758 if (damage > damagetolerance && !dead) {
4761 unconscioustime = 0;
4763 if (creature == wolftype) {
4764 award_bonus(0, Wolfbonus);
4769 if (weaponactive != -1) {
4770 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4771 weapons[weaponids[0]].velocity.x += .01;
4774 weaponids[0] = weaponids[num_weapons];
4775 if (weaponstuck == num_weapons)
4779 for (unsigned i = 0; i < Person::players.size(); i++) {
4780 Person::players[i]->wentforweapon = 0;
4786 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4795 damage -= multiplier * 13;
4797 permanentdamage -= multiplier * 4;
4798 if (isIdle() || isCrouch()) {
4800 permanentdamage -= multiplier * 4;
4804 if (permanentdamage < 0)
4805 permanentdamage = 0;
4806 if (superpermanentdamage < 0)
4807 superpermanentdamage = 0;
4808 if (permanentdamage < superpermanentdamage) {
4809 permanentdamage = superpermanentdamage;
4811 if (damage < permanentdamage) {
4812 damage = permanentdamage;
4814 if (dead == 1 && damage < damagetolerance) {
4818 for (int i = 0; i < skeleton.num_joints; i++) {
4819 skeleton.joints[i].velocity = 0;
4822 if (permanentdamage > damagetolerance && dead != 2) {
4825 if (weaponactive != -1) {
4826 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4827 weapons[weaponids[0]].velocity.x += .01;
4830 weaponids[0] = weaponids[num_weapons];
4831 if (weaponstuck == num_weapons)
4835 for (unsigned i = 0; i < Person::players.size(); i++) {
4836 Person::players[i]->wentforweapon = 0;
4842 if (!dead && creature == wolftype) {
4843 award_bonus(0, Wolfbonus);
4846 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4847 award_bonus(id, touchofdeath);
4848 if (id != 0 && unconscioustime > .1) {
4856 emit_sound_at(breaksound, coords);
4859 if (skeleton.free == 1) {
4861 pause_sound(whooshsound);
4864 //If knocked over, open hands and close mouth
4865 if (righthandmorphend != 0)
4866 righthandmorphness = 0;
4867 righthandmorphend = 0;
4868 targetrighthandmorphness = 1;
4870 if (lefthandmorphend != 0)
4871 lefthandmorphness = 0;
4872 lefthandmorphend = 0;
4873 targetlefthandmorphness = 1;
4875 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4876 if (headmorphend != 0)
4879 targetheadmorphness = 1;
4883 skeleton.DoGravity(&scale);
4885 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4886 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4887 award_bonus(id, deepimpact);
4888 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4892 for (j = 0; j < skeleton.num_joints; j++) {
4893 average += skeleton.joints[j].position;
4897 coords += average * scale;
4898 for (j = 0; j < skeleton.num_joints; j++) {
4899 skeleton.joints[j].position -= average;
4901 average /= multiplier;
4904 for (int i = 0; i < skeleton.num_joints; i++) {
4905 velocity += skeleton.joints[i].velocity * scale;
4907 velocity /= skeleton.num_joints;
4909 if (!isnormal(velocity.x) && velocity.x) {
4913 if (findLength(&average) < 10 && dead && skeleton.free) {
4914 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4915 if (skeleton.longdead > 2000) {
4916 if (skeleton.longdead > 6000) {
4918 pause_sound(whooshsound);
4923 if (dead == 2 && bloodloss < damagetolerance) {
4925 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4927 if (bloodtoggle && !bled) {
4928 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4930 if (bloodtoggle && !bled)
4931 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4932 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4933 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4934 float size = .2 * 1.2;
4937 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4941 if (dead == 2 && bloodloss >= damagetolerance) {
4943 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4946 if (bloodtoggle && !bled) {
4947 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4949 if (bloodtoggle && !bled)
4950 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4951 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4952 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4956 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4963 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4964 bool canrecover = 1;
4965 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4966 startpoint = coords;
4969 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4971 if (velocity.y < -30)
4973 for (i = 0; i < objects.numobjects; i++) {
4974 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4975 colviewer = startpoint;
4976 coltarget = endpoint;
4977 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4986 terrainnormal = jointPos(groin) - jointPos(abdomen);
4987 if (joint(groin).locked && joint(abdomen).locked) {
4988 terrainnormal = jointPos(groin) - jointPos(abdomen);
4989 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4991 if (joint(abdomen).locked && joint(neck).locked) {
4992 terrainnormal = jointPos(abdomen) - jointPos(neck);
4993 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4995 if (joint(groin).locked && joint(neck).locked) {
4996 terrainnormal = jointPos(groin) - jointPos(neck);
4997 middle = (jointPos(groin) + jointPos(neck)) / 2;
4999 Normalise(&terrainnormal);
5001 targetyaw = -asin(0 - terrainnormal.x);
5002 targetyaw *= 360 / 6.28;
5003 if (terrainnormal.z < 0)
5004 targetyaw = 180 - targetyaw;
5008 animTarget = flipanim;
5009 crouchtogglekeydown = 1;
5014 animCurrent = tempanim;
5018 for (int i = 0; i < skeleton.num_joints; i++) {
5019 tempanimation.position[i][0] = skeleton.joints[i].position;
5020 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5025 if (findLength(&average) < 10 && !dead && skeleton.free) {
5026 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5027 if (skeleton.longdead > (damage + 500) * 1.5) {
5029 pause_sound(whooshsound);
5035 terrainnormal = jointPos(groin) - jointPos(abdomen);
5036 if (joint(groin).locked && joint(abdomen).locked) {
5037 terrainnormal = jointPos(groin) - jointPos(abdomen);
5038 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5040 if (joint(abdomen).locked && joint(neck).locked) {
5041 terrainnormal = jointPos(abdomen) - jointPos(neck);
5042 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5044 if (joint(groin).locked && joint(neck).locked) {
5045 terrainnormal = jointPos(groin) - jointPos(neck);
5046 middle = (jointPos(groin) + jointPos(neck)) / 2;
5048 Normalise(&terrainnormal);
5050 targetyaw = -asin(0 - terrainnormal.x);
5051 targetyaw *= 360 / 6.28;
5052 if (terrainnormal.z < 0)
5053 targetyaw = 180 - targetyaw;
5056 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5059 if (skeleton.forward.y < 0) {
5060 animTarget = getupfrombackanim;
5064 if (skeleton.forward.y > -.3) {
5065 animTarget = getupfromfrontanim;
5073 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5074 animTarget = rollanim;
5075 targetyaw = lookyaw;
5092 if ( !leftkeydown && !rightkeydown)
5099 if (abs(targettilt2) > 50)
5101 animCurrent = tempanim;
5104 tilt2 = targettilt2;
5106 if (middle.y > 0 && animTarget != rollanim)
5107 targetoffset.y = middle.y + 1;
5109 for (int i = 0; i < skeleton.num_joints; i++) {
5110 tempanimation.position[i][0] = skeleton.joints[i].position;
5111 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5118 if (num_weapons > 0)
5119 if (weapons[0].getType() == staff)
5121 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5122 if (velocity.y > -30) {
5124 tempvelocity = velocity;
5125 Normalise(&tempvelocity);
5126 targetyaw = -asin(0 - tempvelocity.x);
5127 targetyaw *= 360 / 6.28;
5129 targetyaw = 180 - targetyaw;
5133 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5134 animTarget = rollanim;
5137 animTarget = backhandspringanim;
5143 emit_sound_at(movewhooshsound, coords, 128.);
5145 animCurrent = animTarget;
5146 frameCurrent = frameTarget - 1;
5158 if (skeleton.freefall == 0)
5163 if (aitype != passivetype || skeleton.free == 1)
5164 if (findLengthfast(&velocity) > .1)
5165 for (i = 0; i < objects.numobjects; i++) {
5166 if (objects.type[i] == firetype)
5167 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) {
5169 if (!objects.onfire[i]) {
5170 emit_sound_at(firestartsound, objects.position[i]);
5172 objects.onfire[i] = 1;
5175 if (objects.onfire[i]) {
5180 if (objects.type[i] == bushtype)
5181 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) {
5183 if (!objects.onfire[i]) {
5184 emit_sound_at(firestartsound, objects.position[i]);
5186 objects.onfire[i] = 1;
5190 if (objects.onfire[i]) {
5194 if (objects.messedwith[i] <= 0) {
5198 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5201 addEnvSound(coords, 4 * findLength(&velocity));
5205 if (environment == grassyenvironment)
5206 howmany = findLength(&velocity) * 4;
5207 if (environment == snowyenvironment)
5208 howmany = findLength(&velocity) * 2;
5210 if (environment != desertenvironment)
5211 for (j = 0; j < howmany; j++) {
5212 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5213 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5214 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5217 pos.x += float(abs(Random() % 100) - 50) / 200;
5218 pos.y += float(abs(Random() % 100) - 50) / 200;
5219 pos.z += float(abs(Random() % 100) - 50) / 200;
5220 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);
5221 Sprite::setLastSpriteSpecial(1);
5223 howmany = findLength(&velocity) * 4;
5225 if (environment == snowyenvironment)
5226 for (j = 0; j < howmany; j++) {
5227 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5228 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5229 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5232 pos.x += float(abs(Random() % 100) - 50) / 200;
5233 pos.y += float(abs(Random() % 100) - 50) / 200;
5234 pos.z += float(abs(Random() % 100) - 50) / 200;
5235 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5236 Sprite::setLastSpriteSpecial(2);
5239 objects.rotx[i] += velocity.x * multiplier * 6;
5240 objects.roty[i] += velocity.z * multiplier * 6;
5241 objects.messedwith[i] = .5;
5244 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5245 if (objects.pitch[i] == 0)
5248 tempcoord = coords - objects.position[i];
5249 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5250 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5251 tempcoord += objects.position[i];
5253 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]) {
5254 if (objects.messedwith[i] <= 0) {
5258 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5261 addEnvSound(coords, 4 * findLength(&velocity));
5265 if (environment == grassyenvironment)
5266 howmany = findLength(&velocity) * 4;
5267 if (environment == snowyenvironment)
5268 howmany = findLength(&velocity) * 2;
5270 if (environment != desertenvironment)
5271 for (j = 0; j < howmany; j++) {
5272 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5273 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5274 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5276 pos += velocity * .1;
5278 pos.x += float(abs(Random() % 100) - 50) / 150;
5279 pos.y += float(abs(Random() % 100) - 50) / 150;
5280 pos.z += float(abs(Random() % 100) - 50) / 150;
5281 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);
5282 Sprite::setLastSpriteSpecial(1);
5284 howmany = findLength(&velocity) * 4;
5286 if (environment == snowyenvironment)
5287 for (j = 0; j < howmany; j++) {
5288 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5289 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5290 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5292 pos += velocity * .1;
5294 pos.x += float(abs(Random() % 100) - 50) / 150;
5295 pos.y += float(abs(Random() % 100) - 50) / 150;
5296 pos.z += float(abs(Random() % 100) - 50) / 150;
5297 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5298 Sprite::setLastSpriteSpecial(2);
5301 objects.messedwith[i] = .5;
5306 if (!skeleton.free) {
5309 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5312 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5314 if (tutoriallevel == 1 && id != 0)
5316 if (play && aitype != playercontrolled) {
5317 int whichsound = -1;
5318 i = abs(Random() % 4);
5319 if (speechdelay <= 0) {
5320 if (creature == rabbittype) {
5322 whichsound = rabbitchitter;
5324 whichsound = rabbitchitter2;
5326 if (creature == wolftype) {
5328 whichsound = growlsound;
5330 whichsound = growl2sound;
5335 if (whichsound != -1) {
5336 emit_sound_at(whichsound, coords);
5340 if (animTarget == staggerbackhighanim)
5342 if (animTarget == staggerbackhardanim)
5344 staggerdelay -= multiplier;
5345 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5347 if (velocity.y < -30 && animTarget == jumpdownanim)
5349 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5350 animTarget = getIdle();
5354 weaponmissdelay -= multiplier;
5355 highreversaldelay -= multiplier;
5356 lowreversaldelay -= multiplier;
5357 lastcollide -= multiplier;
5358 skiddelay -= multiplier;
5359 if (!isnormal(velocity.x) && velocity.x) {
5362 if (!isnormal(targettilt) && targettilt) {
5365 if (!isnormal(targettilt2) && targettilt2) {
5368 if (!isnormal(targetyaw) && targetyaw) {
5372 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5373 //open hands and close mouth
5374 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5375 righthandmorphness = 0;
5376 righthandmorphend = 0;
5377 targetrighthandmorphness = 1;
5380 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5381 lefthandmorphness = 0;
5382 lefthandmorphend = 0;
5383 targetlefthandmorphness = 1;
5386 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5389 targetheadmorphness = 1;
5393 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) {
5394 //open hands and mouth
5395 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5396 righthandmorphness = 0;
5397 righthandmorphend = 0;
5398 targetrighthandmorphness = 1;
5401 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5402 lefthandmorphness = 0;
5403 lefthandmorphend = 0;
5404 targetlefthandmorphness = 1;
5407 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5410 targetheadmorphness = 1;
5414 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5415 //close hands and mouth
5416 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5417 righthandmorphness = 0;
5418 righthandmorphend = 1;
5419 targetrighthandmorphness = 1;
5422 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5423 lefthandmorphness = 0;
5424 lefthandmorphend = 1;
5425 targetlefthandmorphness = 1;
5428 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5431 targetheadmorphness = 1;
5435 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) {
5436 //close hands and yell
5437 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5438 righthandmorphness = 0;
5439 righthandmorphend = 1;
5440 targetrighthandmorphness = 1;
5443 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5444 lefthandmorphness = 0;
5445 lefthandmorphend = 1;
5446 targetlefthandmorphness = 1;
5449 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5452 targetheadmorphness = 1;
5459 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5460 (victim->aitype != searchtype) && (aitype != passivetype) &&
5461 (aitype != searchtype) && (victim->id < Person::players.size())) {
5462 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5466 if (!dead && animTarget != hurtidleanim)
5467 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5468 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5471 targetheadmorphness = 1;
5475 if (weaponactive != -1) {
5476 if (weapons[weaponids[weaponactive]].getType() != staff) {
5477 righthandmorphstart = 1;
5478 righthandmorphend = 1;
5480 if (weapons[weaponids[weaponactive]].getType() == staff) {
5481 righthandmorphstart = 2;
5482 righthandmorphend = 2;
5484 targetrighthandmorphness = 1;
5487 terrainnormal = terrain.getNormal(coords.x, coords.z);
5489 if (animation[animTarget].attack != reversal) {
5490 if (!isnormal(coords.x))
5498 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5499 facing = flatfacing;
5500 ReflectVector(&facing, terrainnormal);
5503 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5505 targettilt2 = -facing.y * 20;
5510 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5512 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5513 flatvelocity = velocity;
5515 flatvelspeed = findLength(&flatvelocity);
5516 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5517 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5522 if (targettilt > 25)
5524 if (targettilt < -25)
5528 if (targettilt2 > 45)
5530 if (targettilt2 < -45)
5532 if (abs(tilt2 - targettilt2) < multiplier * 400)
5533 tilt2 = targettilt2;
5534 else if (tilt2 > targettilt2) {
5535 tilt2 -= multiplier * 400;
5536 } else if (tilt2 < targettilt2) {
5537 tilt2 += multiplier * 400;
5539 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5546 if (!isnormal(targettilt) && targettilt) {
5549 if (!isnormal(targettilt2) && targettilt2) {
5554 if (animTarget == rabbittackleanim) {
5555 velocity += facing * multiplier * speed * 700 * scale;
5556 velspeed = findLength(&velocity);
5557 if (velspeed > speed * 65 * scale) {
5558 velocity /= velspeed;
5559 velspeed = speed * 65 * scale;
5560 velocity *= velspeed;
5562 velocity.y += gravity * multiplier * 20;
5563 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5564 velspeed = findLength(&velocity);
5565 velocity = flatfacing * velspeed;
5567 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5568 if (isRun() || animTarget == rabbitkickanim) {
5569 velocity += facing * multiplier * speed * 700 * scale;
5570 velspeed = findLength(&velocity);
5571 if (velspeed > speed * 45 * scale) {
5572 velocity /= velspeed;
5573 velspeed = speed * 45 * scale;
5574 velocity *= velspeed;
5576 velocity.y += gravity * multiplier * 20;
5577 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5578 velspeed = findLength(&velocity);
5579 if (velspeed < speed * 30 * scale)
5580 velspeed = speed * 30 * scale;
5581 velocity = flatfacing * velspeed;
5583 } else if (isRun()) {
5584 velocity += facing * multiplier * speed * 700 * scale;
5585 velspeed = findLength(&velocity);
5586 if (creature == rabbittype) {
5587 if (velspeed > speed * 55 * scale) {
5588 velocity /= velspeed;
5589 velspeed = speed * 55 * scale;
5590 velocity *= velspeed;
5593 if (creature == wolftype) {
5594 if (velspeed > speed * 75 * scale) {
5595 velocity /= velspeed;
5596 velspeed = speed * 75 * scale;
5597 velocity *= velspeed;
5600 velocity.y += gravity * multiplier * 20;
5601 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5602 velspeed = findLength(&velocity);
5603 velocity = flatfacing * velspeed;
5606 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5607 velocity += facing * multiplier * speed * 700 * scale;
5608 velspeed = findLength(&velocity);
5609 if (velspeed > speed * 45 * scale) {
5610 velocity /= velspeed;
5611 velspeed = speed * 45 * scale;
5612 velocity *= velspeed;
5614 velocity.y += gravity * multiplier * 20;
5615 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5616 velspeed = findLength(&velocity);
5617 velocity = flatfacing * velspeed;
5620 if (animTarget == sneakanim || animTarget == walkanim) {
5621 velocity += facing * multiplier * speed * 700 * scale;
5622 velspeed = findLength(&velocity);
5623 if (velspeed > speed * 12 * scale) {
5624 velocity /= velspeed;
5625 velspeed = speed * 12 * scale;
5626 velocity *= velspeed;
5628 velocity.y += gravity * multiplier * 20;
5629 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5630 velspeed = findLength(&velocity);
5631 velocity = flatfacing * velspeed;
5634 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5635 velocity += facing * multiplier * speed * 700 * scale;
5636 velspeed = findLength(&velocity);
5637 if (velspeed > speed * 2 * scale) {
5638 velocity /= velspeed;
5639 velspeed = speed * 2 * scale;
5640 velocity *= velspeed;
5642 velocity.y += gravity * multiplier * 20;
5643 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5644 velspeed = findLength(&velocity);
5645 velocity = flatfacing * velspeed;
5649 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5650 velocity -= facing * multiplier * speed * 700 * scale;
5651 velspeed = findLength(&velocity);
5652 if (velspeed > speed * 2 * scale) {
5653 velocity /= velspeed;
5654 velspeed = speed * 2 * scale;
5655 velocity *= velspeed;
5657 velocity.y += gravity * multiplier * 20;
5658 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5659 velspeed = findLength(&velocity);
5660 velocity = flatfacing * velspeed * -1;
5663 if (animTarget == fightsidestep) {
5664 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5665 velspeed = findLength(&velocity);
5666 if (velspeed > speed * 12 * scale) {
5667 velocity /= velspeed;
5668 velspeed = speed * 12 * scale;
5669 velocity *= velspeed;
5671 velocity.y += gravity * multiplier * 20;
5672 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5673 velspeed = findLength(&velocity);
5674 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5677 if (animTarget == staggerbackhighanim) {
5678 coords -= facing * multiplier * speed * 16 * scale;
5681 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5682 coords -= facing * multiplier * speed * 20 * scale;
5686 if (animTarget == backhandspringanim) {
5687 //coords-=facing*multiplier*50*scale;
5688 velocity += facing * multiplier * speed * 700 * scale * -1;
5689 velspeed = findLength(&velocity);
5690 if (velspeed > speed * 50 * scale) {
5691 velocity /= velspeed;
5692 velspeed = speed * 50 * scale;
5693 velocity *= velspeed;
5695 velocity.y += gravity * multiplier * 20;
5696 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5697 velspeed = findLength(&velocity);
5698 velocity = flatfacing * velspeed * -1;
5700 if (animTarget == dodgebackanim) {
5701 //coords-=facing*multiplier*50*scale;
5702 velocity += facing * multiplier * speed * 700 * scale * -1;
5703 velspeed = findLength(&velocity);
5704 if (velspeed > speed * 60 * scale) {
5705 velocity /= velspeed;
5706 velspeed = speed * 60 * scale;
5707 velocity *= velspeed;
5709 velocity.y += gravity * multiplier * 20;
5710 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5711 velspeed = findLength(&velocity);
5712 velocity = flatfacing * velspeed * -1;
5715 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5716 velspeed = findLength(&velocity);
5720 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5721 velocity.y += gravity * multiplier;
5724 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5725 coords += velocity * multiplier;
5727 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5728 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5731 if (animTarget == jumpupanim) {
5733 animTarget = getIdle();
5740 pause_sound(whooshsound);
5741 OPENAL_SetVolume(channels[whooshsound], 0);
5744 if (animTarget == jumpdownanim || isFlip()) {
5745 if (isFlip())jumppower = -4;
5746 animTarget = getLanding();
5747 emit_sound_at(landsound, coords, 128.);
5750 addEnvSound(coords);
5755 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5756 coords.y += gravity * multiplier * 2;
5757 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5758 coords.y = terrain.getHeight(coords.x, coords.z);
5763 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)) {
5764 velspeed = findLength(&velocity);
5766 if (velspeed < multiplier * 300 * scale) {
5769 velocity -= velocity / velspeed * multiplier * 300 * scale;
5770 if (velspeed > 5 && (isLanding() || isLandhard())) {
5771 skiddingdelay += multiplier;
5772 if (skiddelay <= 0) {
5782 velspeed = findLength(&velocity);
5784 if (velspeed < multiplier * 600 * scale) {
5787 velocity -= velocity / velspeed * multiplier * 600 * scale;
5789 if (velspeed > 5 && (isLanding() || isLandhard())) {
5790 skiddingdelay += multiplier;
5791 if (skiddelay <= 0) {
5800 if (skiddingdelay < 0)
5801 skiddingdelay += multiplier;
5802 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5804 if (!onterrain || environment == grassyenvironment) {
5805 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5807 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5811 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5812 terrainnormal = victim->coords - coords;
5813 Normalise(&terrainnormal);
5814 targetyaw = -asin(0 - terrainnormal.x);
5815 targetyaw *= 360 / 6.28;
5816 if (terrainnormal.z < 0)
5817 targetyaw = 180 - targetyaw;
5818 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5821 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5822 targetyaw = victim->targetyaw;
5824 if (animTarget == rabbittacklinganim) {
5825 coords = victim->coords;
5828 skeleton.oldfree = skeleton.free;
5832 midterrain.x = terrain.size * terrain.scale / 2;
5833 midterrain.z = terrain.size * terrain.scale / 2;
5834 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5836 tempposit = coords - midterrain;
5838 Normalise(&tempposit);
5839 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5840 coords.x = tempposit.x + midterrain.x;
5841 coords.z = tempposit.z + midterrain.z;
5847 * inverse kinematics helper function
5849 void IKHelper(Person *p, float interp)
5851 XYZ point, change, change2;
5852 float heightleft, heightright;
5854 // TODO: implement localToWorld and worldToLocal
5855 // but keep in mind it won't be the same math if player is ragdolled or something
5856 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5857 // then comb through code for places where to use it
5859 // point = localToWorld(jointPos(leftfoot))
5860 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5861 // adjust height of foot
5862 heightleft = terrain.getHeight(point.x, point.z) + .04;
5863 point.y = heightleft;
5864 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5865 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5866 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5867 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5868 // move ankle along with foot
5869 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5870 // average knee pos between old and new pos
5871 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5873 // do same as above for right leg
5874 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5875 heightright = terrain.getHeight(point.x, point.z) + .04;
5876 point.y = heightright;
5877 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5878 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5879 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5880 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5881 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5883 // fix up skeleton now that we've moved body parts?
5884 p->skeleton.DoConstraints(&p->coords, &p->scale);
5891 int Person::DrawSkeleton()
5893 int oldplayerdetail;
5894 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5895 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5905 glAlphaFunc(GL_GREATER, 0.0001);
5907 float terrainheight;
5911 if (!isnormal(tilt))
5913 if (!isnormal(tilt2))
5915 oldplayerdetail = playerdetail;
5917 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5920 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5923 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5928 if (playerdetail != oldplayerdetail) {
5930 normalsupdatedelay = 0;
5932 static float updatedelaychange;
5933 static float morphness;
5934 static float framemult;
5936 skeleton.FindForwards();
5937 if (howactive == typesittingwall) {
5938 skeleton.specialforward[1] = 0;
5939 skeleton.specialforward[1].z = 1;
5945 static int weaponattachmuscle;
5946 static int weaponrotatemuscle;
5947 static XYZ weaponpoint;
5948 static int start, endthing;
5949 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5950 if (!isSleeping() && !isSitting()) {
5951 // TODO: give these meaningful names
5952 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5953 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5954 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5955 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5957 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5959 if (creature == wolftype)
5963 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5964 IKHelper(this, target);
5965 if (creature == wolftype)
5966 IKHelper(this, target);
5969 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5970 IKHelper(this, 1 - target);
5971 if (creature == wolftype)
5972 IKHelper(this, 1 - target);
5976 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()))
5979 targetheadyaw = -targetyaw;
5980 targetheadpitch = 0;
5981 if (animation[animTarget].attack == 3)
5982 targetheadyaw += 180;
5984 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5985 skeleton.drawmodel.vertex[i] = 0;
5986 skeleton.drawmodel.vertex[i].y = 999;
5988 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5989 skeleton.drawmodellow.vertex[i] = 0;
5990 skeleton.drawmodellow.vertex[i].y = 999;
5992 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5993 skeleton.drawmodelclothes.vertex[i] = 0;
5994 skeleton.drawmodelclothes.vertex[i].y = 999;
5996 for (int i = 0; i < skeleton.num_muscles; i++) {
5997 // convenience renames
5998 const int p1 = skeleton.muscles[i].parent1->label;
5999 const int p2 = skeleton.muscles[i].parent2->label;
6001 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6006 if (p1 == righthand || p2 == righthand) {
6007 morphness = righthandmorphness;
6008 start = righthandmorphstart;
6009 endthing = righthandmorphend;
6011 if (p1 == lefthand || p2 == lefthand) {
6012 morphness = lefthandmorphness;
6013 start = lefthandmorphstart;
6014 endthing = lefthandmorphend;
6016 if (p1 == head || p2 == head) {
6017 morphness = headmorphness;
6018 start = headmorphstart;
6019 endthing = headmorphend;
6021 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6022 morphness = chestmorphness;
6023 start = chestmorphstart;
6024 endthing = chestmorphend;
6026 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6027 morphness = tailmorphness;
6028 start = tailmorphstart;
6029 endthing = tailmorphend;
6032 skeleton.FindRotationMuscle(i, animTarget);
6033 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6034 glMatrixMode(GL_MODELVIEW);
6038 glRotatef(tilt2, 1, 0, 0);
6040 glRotatef(tilt, 0, 0, 1);
6043 glTranslatef(mid.x, mid.y, mid.z);
6045 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6046 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6048 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6049 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6051 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6052 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6054 if (playerdetail || skeleton.free == 3) {
6055 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6056 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6057 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6058 glMatrixMode(GL_MODELVIEW);
6060 if (p1 == abdomen || p2 == abdomen)
6061 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6062 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6063 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6064 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6065 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6066 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6067 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6068 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6069 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6070 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6071 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6072 if (p1 == head || p2 == head)
6073 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6074 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6075 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6076 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6077 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6078 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6079 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6083 if (!playerdetail || skeleton.free == 3) {
6084 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6085 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6086 glMatrixMode(GL_MODELVIEW);
6088 if (p1 == abdomen || p2 == abdomen)
6089 glTranslatef(v0.x * proportionbody.x,
6090 v0.y * proportionbody.y,
6091 v0.z * proportionbody.z);
6092 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6093 glTranslatef(v0.x * proportionarms.x,
6094 v0.y * proportionarms.y,
6095 v0.z * proportionarms.z);
6096 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6097 glTranslatef(v0.x * proportionlegs.x,
6098 v0.y * proportionlegs.y,
6099 v0.z * proportionlegs.z);
6100 if (p1 == head || p2 == head)
6101 glTranslatef(v0.x * proportionhead.x,
6102 v0.y * proportionhead.y,
6103 v0.z * proportionhead.z);
6105 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6106 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6107 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6108 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6114 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6115 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6117 glMatrixMode(GL_MODELVIEW);
6121 glRotatef(tilt2, 1, 0, 0);
6123 glRotatef(tilt, 0, 0, 1);
6124 glTranslatef(mid.x, mid.y, mid.z);
6125 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6126 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6128 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6129 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6131 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6132 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6134 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6135 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6136 glMatrixMode(GL_MODELVIEW);
6138 if (p1 == abdomen || p2 == abdomen)
6139 glTranslatef(v0.x * proportionbody.x,
6140 v0.y * proportionbody.y,
6141 v0.z * proportionbody.z);
6142 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6143 glTranslatef(v0.x * proportionarms.x,
6144 v0.y * proportionarms.y,
6145 v0.z * proportionarms.z);
6146 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6147 glTranslatef(v0.x * proportionlegs.x,
6148 v0.y * proportionlegs.y,
6149 v0.z * proportionlegs.z);
6150 if (p1 == head || p2 == head)
6151 glTranslatef(v0.x * proportionhead.x,
6152 v0.y * proportionhead.y,
6153 v0.z * proportionhead.z);
6154 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6155 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6156 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6157 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6162 updatedelay = 1 + (float)(Random() % 100) / 1000;
6164 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6165 normalsupdatedelay = 1;
6166 if (playerdetail || skeleton.free == 3)
6167 skeleton.drawmodel.CalculateNormals(0);
6168 if (!playerdetail || skeleton.free == 3)
6169 skeleton.drawmodellow.CalculateNormals(0);
6170 if (skeleton.clothes)
6171 skeleton.drawmodelclothes.CalculateNormals(0);
6173 if (playerdetail || skeleton.free == 3)
6174 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6175 if (!playerdetail || skeleton.free == 3)
6176 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6177 if (skeleton.clothes) {
6178 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6183 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6184 if (updatedelaychange > -realmultiplier * 30)
6185 updatedelaychange = -realmultiplier * 30;
6186 if (updatedelaychange > -framemult * 4)
6187 updatedelaychange = -framemult * 4;
6188 if (skeleton.free == 1)
6189 updatedelaychange *= 6;
6191 updatedelaychange *= 8;
6192 updatedelay += updatedelaychange;
6194 glMatrixMode(GL_MODELVIEW);
6196 glTranslatef(coords.x, coords.y - .02, coords.z);
6197 if (!skeleton.free) {
6198 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6199 glRotatef(yaw, 0, 1, 0);
6203 glColor4f(.4, 1, .4, 1);
6204 glDisable(GL_LIGHTING);
6205 glDisable(GL_TEXTURE_2D);
6208 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6209 XYZ &v0 = skeleton.drawmodel.vertex[i];
6210 glVertex3f(v0.x, v0.y, v0.z);
6216 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6217 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6218 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6219 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6220 glVertex3f(v0.x, v0.y, v0.z);
6221 glVertex3f(v1.x, v1.y, v1.z);
6222 glVertex3f(v1.x, v1.y, v1.z);
6223 glVertex3f(v2.x, v2.y, v2.z);
6224 glVertex3f(v2.x, v2.y, v2.z);
6225 glVertex3f(v0.x, v0.y, v0.z);
6231 terrainlight = terrain.getLighting(coords.x, coords.z);
6232 distance = distsq(&viewer, &coords);
6233 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6237 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6238 if (terrainheight < 1)
6240 if (terrainheight > 1.7)
6241 terrainheight = 1.7;
6244 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6245 glDisable(GL_BLEND);
6246 glAlphaFunc(GL_GREATER, 0.0001);
6247 glEnable(GL_TEXTURE_2D);
6249 glDisable(GL_TEXTURE_2D);
6250 glColor4f(.7, .35, 0, .5);
6252 glEnable(GL_LIGHTING);
6255 if (tutoriallevel && id != 0) {
6256 glColor4f(.7, .7, .7, 0.6);
6258 glEnable(GL_LIGHTING);
6260 if (canattack && cananger)
6261 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6262 glDisable(GL_TEXTURE_2D);
6263 glColor4f(1, 0, 0, 0.8);
6265 glMatrixMode(GL_TEXTURE);
6267 glTranslatef(0, -smoketex, 0);
6268 glTranslatef(-smoketex, 0, 0);
6272 if ((tutoriallevel && id != 0))
6273 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6275 skeleton.drawmodel.draw();
6278 if (!playerdetail) {
6279 if ((tutoriallevel && id != 0))
6280 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6282 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6285 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6286 if (tutoriallevel && id != 0) {
6288 glMatrixMode(GL_MODELVIEW);
6289 glEnable(GL_TEXTURE_2D);
6290 glColor4f(.7, .7, .7, 0.6);
6292 glEnable(GL_LIGHTING);
6294 if (canattack && cananger)
6295 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6296 glDisable(GL_TEXTURE_2D);
6297 glColor4f(1, 0, 0, 0.8);
6299 glMatrixMode(GL_TEXTURE);
6301 glTranslatef(0, -smoketex * .6, 0);
6302 glTranslatef(smoketex * .6, 0, 0);
6305 if ((tutoriallevel && id != 0))
6306 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6308 skeleton.drawmodel.draw();
6311 if (!playerdetail) {
6312 if ((tutoriallevel && id != 0))
6313 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6315 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6320 if (tutoriallevel && id != 0) {
6322 glMatrixMode(GL_MODELVIEW);
6323 glEnable(GL_TEXTURE_2D);
6325 if (skeleton.clothes) {
6329 skeleton.drawmodelclothes.draw();
6331 skeleton.drawmodelclothes.drawimmediate();
6337 if (num_weapons > 0) {
6338 for (k = 0; k < num_weapons; k++) {
6340 if (weaponactive == k) {
6341 if (weapons[i].getType() != staff) {
6342 for (j = 0; j < skeleton.num_muscles; j++) {
6343 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6344 weaponattachmuscle = j;
6347 for (j = 0; j < skeleton.num_muscles; j++) {
6348 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) {
6349 weaponrotatemuscle = j;
6352 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6353 if (creature == wolftype)
6354 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6356 if (weapons[i].getType() == staff) {
6357 for (j = 0; j < skeleton.num_muscles; j++) {
6358 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6359 weaponattachmuscle = j;
6362 for (j = 0; j < skeleton.num_muscles; j++) {
6363 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) {
6364 weaponrotatemuscle = j;
6367 //weaponpoint=jointPos(rightwrist);
6368 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6369 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6370 XYZ tempnormthing, vec1, vec2;
6371 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6372 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6373 CrossProduct(&vec1, &vec2, &tempnormthing);
6374 Normalise(&tempnormthing);
6375 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6376 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6379 if (weaponactive != k && weaponstuck != k) {
6380 if (weapons[i].getType() == knife)
6381 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6382 if (weapons[i].getType() == sword)
6383 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6384 if (weapons[i].getType() == staff)
6385 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6386 for (j = 0; j < skeleton.num_muscles; j++) {
6387 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) {
6388 weaponrotatemuscle = j;
6392 if (weaponstuck == k) {
6393 if (weaponstuckwhere == 0)
6394 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6396 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
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 (skeleton.free) {
6404 weapons[i].position = weaponpoint * scale + coords;
6405 weapons[i].bigrotation = 0;
6406 weapons[i].bigtilt = 0;
6407 weapons[i].bigtilt2 = 0;
6409 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;
6410 weapons[i].bigrotation = yaw;
6411 weapons[i].bigtilt = tilt;
6412 weapons[i].bigtilt2 = tilt2;
6414 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6415 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6416 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6417 if (weaponactive == k) {
6418 if (weapons[i].getType() == knife) {
6419 weapons[i].smallrotation = 180;
6420 weapons[i].smallrotation2 = 0;
6421 if (isCrouch() || wasCrouch()) {
6422 weapons[i].smallrotation2 = 20;
6424 if (animTarget == hurtidleanim) {
6425 weapons[i].smallrotation2 = 50;
6427 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6428 XYZ temppoint1, temppoint2;
6431 temppoint1 = jointPos(righthand);
6432 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6433 distance = findDistance(&temppoint1, &temppoint2);
6434 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6435 weapons[i].rotation2 *= 360 / 6.28;
6438 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6439 weapons[i].rotation1 *= 360 / 6.28;
6440 weapons[i].rotation3 = 0;
6441 weapons[i].smallrotation = -90;
6442 weapons[i].smallrotation2 = 0;
6443 if (temppoint1.x > temppoint2.x)
6444 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6446 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6447 XYZ temppoint1, temppoint2;
6450 temppoint1 = jointPos(righthand);
6451 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6452 distance = findDistance(&temppoint1, &temppoint2);
6453 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6454 weapons[i].rotation2 *= 360 / 6.28;
6457 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6458 weapons[i].rotation1 *= 360 / 6.28;
6459 weapons[i].rotation3 = 0;
6460 weapons[i].smallrotation = 90;
6461 weapons[i].smallrotation2 = 0;
6462 if (temppoint1.x > temppoint2.x)
6463 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6465 if (animTarget == knifethrowanim) {
6466 weapons[i].smallrotation = 90;
6467 //weapons[i].smallrotation2=-90;
6468 weapons[i].smallrotation2 = 0;
6469 weapons[i].rotation1 = 0;
6470 weapons[i].rotation2 = 0;
6471 weapons[i].rotation3 = 0;
6473 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6474 weapons[i].smallrotation = -90;
6475 weapons[i].rotation1 = 0;
6476 weapons[i].rotation2 = 0;
6477 weapons[i].rotation3 = 0;
6480 if (weapons[i].getType() == sword) {
6481 weapons[i].smallrotation = 0;
6482 weapons[i].smallrotation2 = 0;
6483 if (animTarget == knifethrowanim) {
6484 weapons[i].smallrotation = -90;
6485 weapons[i].smallrotation2 = 0;
6486 weapons[i].rotation1 = 0;
6487 weapons[i].rotation2 = 0;
6488 weapons[i].rotation3 = 0;
6490 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)) {
6491 XYZ temppoint1, temppoint2;
6494 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6495 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6496 distance = findDistance(&temppoint1, &temppoint2);
6497 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6498 weapons[i].rotation2 *= 360 / 6.28;
6501 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6502 weapons[i].rotation1 *= 360 / 6.28;
6503 weapons[i].rotation3 = 0;
6504 weapons[i].smallrotation = 90;
6505 weapons[i].smallrotation2 = 0;
6506 if (temppoint1.x > temppoint2.x)
6507 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6510 if (weapons[i].getType() == staff) {
6511 weapons[i].smallrotation = 100;
6512 weapons[i].smallrotation2 = 0;
6513 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6514 XYZ temppoint1, temppoint2;
6517 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6518 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6519 distance = findDistance(&temppoint1, &temppoint2);
6520 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6521 weapons[i].rotation2 *= 360 / 6.28;
6524 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6525 weapons[i].rotation1 *= 360 / 6.28;
6526 weapons[i].rotation3 = 0;
6527 weapons[i].smallrotation = 90;
6528 weapons[i].smallrotation2 = 0;
6529 if (temppoint1.x > temppoint2.x)
6530 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6534 if (weaponactive != k && weaponstuck != k) {
6535 if (weapons[i].getType() == knife) {
6536 weapons[i].smallrotation = -70;
6537 weapons[i].smallrotation2 = 10;
6539 if (weapons[i].getType() == sword) {
6540 weapons[i].smallrotation = -100;
6541 weapons[i].smallrotation2 = -8;
6543 if (weapons[i].getType() == staff) {
6544 weapons[i].smallrotation = -100;
6545 weapons[i].smallrotation2 = -8;
6548 if (weaponstuck == k) {
6549 if (weaponstuckwhere == 0)
6550 weapons[i].smallrotation = 180;
6552 weapons[i].smallrotation = 0;
6553 weapons[i].smallrotation2 = 10;
6562 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6564 if (animCurrent != animTarget)
6566 if (skeleton.free == 2)
6575 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6578 static float distance;
6579 static float olddistance;
6580 static int intersecting;
6581 static int firstintersecting;
6584 static XYZ start, end;
6585 static float slopethreshold = -.4;
6587 firstintersecting = -1;
6591 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6594 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6595 for (i = 0; i < 4; i++) {
6596 for (j = 0; j < model->TriangleNum; j++) {
6597 if (model->facenormals[j].y <= slopethreshold) {
6599 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)));
6600 if (distance < radius) {
6601 point = *p1 - model->facenormals[j] * distance;
6602 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]]))
6605 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6606 &model->vertex[model->Triangles[j].vertex[1]],
6609 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6610 &model->vertex[model->Triangles[j].vertex[2]],
6613 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6614 &model->vertex[model->Triangles[j].vertex[2]],
6617 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6621 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)) {
6622 p1->y = point.y + radius;
6623 if ((animTarget == jumpdownanim || isFlip())) {
6624 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6627 if (animTarget == jumpupanim) {
6629 animTarget = getIdle();
6636 pause_sound(whooshsound);
6637 OPENAL_SetVolume(channels[whooshsound], 0);
6640 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6643 animTarget = getLanding();
6644 emit_sound_at(landsound, coords, 128.);
6647 addEnvSound(coords);
6654 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6655 olddistance = distance;
6656 firstintersecting = j;
6661 for (j = 0; j < model->TriangleNum; j++) {
6662 if (model->facenormals[j].y > slopethreshold) {
6665 start.y -= radius / 4;
6666 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6667 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6668 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6669 distance = abs((model->facenormals[j].x * start.x)
6670 + (model->facenormals[j].y * start.y)
6671 + (model->facenormals[j].z * start.z)
6672 - ((model->facenormals[j].x * v0.x)
6673 + (model->facenormals[j].y * v0.y)
6674 + (model->facenormals[j].z * v0.z)));
6675 if (distance < radius * .5) {
6676 point = start - model->facenormals[j] * distance;
6677 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6680 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6682 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6684 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6686 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6687 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6689 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6690 if (findLengthfast(&start) < findLengthfast(&velocity))
6693 *p1 += model->facenormals[j] * (distance - radius * .5);
6696 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6697 olddistance = distance;
6698 firstintersecting = j;
6705 *p = DoRotation(*p, 0, *rotate, 0);
6708 *p1 = DoRotation(*p1, 0, *rotate, 0);
6710 return firstintersecting;
6713 void Person::takeWeapon(int weaponId)
6716 weapons[weaponId].owner = id;
6717 if (num_weapons > 0) {
6718 weaponids[num_weapons] = weaponids[0];
6721 weaponids[0] = weaponId;
6724 void Person::addClothes()
6726 if (numclothes > 0) {
6727 for (int i = 0; i < numclothes; i++) {
6734 bool Person::addClothes(const int& clothesId)
6737 const char* fileName = clothes[clothesId];
6739 GLubyte* array = &skeleton.skinText[0];
6743 bool opened = load_image(fileName, texture);
6748 float tintr = clothestintr[clothesId];
6749 float tintg = clothestintg[clothesId];
6750 float tintb = clothestintb[clothesId];
6752 if (tintr > 1) tintr = 1;
6753 if (tintg > 1) tintg = 1;
6754 if (tintb > 1) tintb = 1;
6756 if (tintr < 0) tintr = 0;
6757 if (tintg < 0) tintg = 0;
6758 if (tintb < 0) tintb = 0;
6760 int bytesPerPixel = texture.bpp / 8;
6764 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6765 if (bytesPerPixel == 3)
6767 else if ((i + 1) % 4 == 0)
6768 alphanum = texture.data[i];
6769 if ((i + 1) % 4 || bytesPerPixel == 3) {
6771 texture.data[i] *= tintr;
6773 texture.data[i] *= tintg;
6775 texture.data[i] *= tintb;
6776 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);