2 Copyright (C) 2003, 2010 - Wolfire Games
4 This file is part of Lugaru.
6 Lugaru is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 Lugaru is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
20 /**> HEADER FILES <**/
22 #include "openal_wrapper.h"
23 #include "Animation.h"
28 extern float multiplier;
29 extern Terrain terrain;
31 extern int environment;
33 extern FRUSTUM frustum;
35 extern float realmultiplier;
37 extern float slomodelay;
38 extern bool cellophane;
39 extern float texdetail;
40 extern float realtexdetail;
41 extern GLubyte bloodText[512 * 512 * 3];
42 extern GLubyte wolfbloodText[512 * 512 * 3];
43 extern int bloodtoggle;
44 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern float flashamount, flashr, flashg, flashb;
57 extern int flashdelay;
58 extern bool showpoints;
59 extern bool immediate;
61 extern bool tilt2weird;
62 extern bool tiltweird;
64 extern bool proportionweird;
65 extern bool vertexweird[6];
66 extern XYZ envsound[30];
67 extern float envsoundvol[30];
68 extern float envsoundlife[30];
69 extern int numenvsounds;
70 extern int tutoriallevel;
71 extern float smoketex;
72 extern int tutorialstage;
73 extern bool reversaltrain;
74 extern bool canattack;
76 extern float damagedealt;
78 extern float hostiletime;
80 extern int indialogue;
82 extern bool gamestarted;
84 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
89 * GameTick/doPlayerCollisions
91 void Person::CheckKick()
94 && (animTarget == rabbitkickanim
96 && victim != this->shared_from_this()
98 && animCurrent == rabbitkickanim)
99 && distsq(&coords, &victim->coords) < 1.2
100 && !victim->skeleton.free))
103 if (animation[victim->animTarget].height != lowheight) {
104 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
105 XYZ relative = velocity;
107 Normalise(&relative);
111 if (tutoriallevel != 1)
112 emit_sound_at(heavyimpactsound, victim->coords);
114 for (int i = 0; i < victim->skeleton.num_joints; i++) {
115 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
118 victim->DoDamage(100 * damagemult / victim->protectionhigh);
124 animTarget = backflipanim;
126 velocity = facing * -10;
130 resume_stream(whooshsound);
132 award_bonus(id, cannon);
133 } else if (victim->isCrouch()) {
134 animTarget = rabbitkickreversedanim;
135 animCurrent = rabbitkickreversedanim;
136 victim->animCurrent = rabbitkickreversalanim;
137 victim->animTarget = rabbitkickreversalanim;
143 victim->oldcoords = victim->coords;
144 coords = victim->coords;
145 victim->targetyaw = targetyaw;
146 victim->victim = this->shared_from_this();
153 * GameTick/doPlayerCollisions - spread fire between players
154 * GameTick/doDebugKeys - press f to ignite
155 * Person::DoStuff - spread fire from lit campfires and bushes
157 void Person::CatchFire()
159 XYZ flatfacing, flatvelocity;
161 for (int i = 0; i < 10; i++) {
162 howmany = abs(Random() % (skeleton.num_joints));
164 flatvelocity = velocity;
166 flatvelocity = skeleton.joints[howmany].velocity;
168 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
170 flatfacing = skeleton.joints[howmany].position * scale + coords;
171 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
176 emit_sound_at(firestartsound, coords);
178 emit_stream_at(stream_firesound, coords);
186 * idle animation for this creature (depending on status)
188 int Person::getIdle()
190 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
192 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
193 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
194 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
195 victim->id < Person::players.size())) {
196 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
197 if (creature == rabbittype)
198 return fightidleanim;
199 if (creature == wolftype)
202 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
203 if (weapons[weaponids[weaponactive]].getType() == knife)
204 return knifefightidleanim;
205 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
206 return swordfightidlebothanim;
207 if (weapons[weaponids[weaponactive]].getType() == sword)
208 return swordfightidleanim;
209 if (weapons[weaponids[weaponactive]].getType() == staff)
210 return swordfightidleanim;
212 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
213 return fightsidestep;
215 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
217 if (howactive == typesitting) return sitanim;
218 if (howactive == typesittingwall) return sitwallanim;
219 if (howactive == typesleeping) return sleepanim;
220 if (howactive == typedead1) return dead1anim;
221 if (howactive == typedead2) return dead2anim;
222 if (howactive == typedead3) return dead3anim;
223 if (howactive == typedead4) return dead4anim;
224 if (creature == rabbittype) return bounceidleanim;
225 if (creature == wolftype) return wolfidle;
230 * crouch animation for this creature
232 int Person::getCrouch()
234 if (creature == rabbittype)
236 if (creature == wolftype)
237 return wolfcrouchanim;
242 * running animation for this creature (can be upright or all fours)
246 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
248 if (creature == wolftype && (!superruntoggle))
251 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
252 return rabbitrunninganim;
253 if (creature == wolftype && (superruntoggle))
254 return wolfrunninganim;
260 int Person::getStop()
262 if (creature == rabbittype)
264 if (creature == wolftype)
271 int Person::getLanding()
273 if (creature == rabbittype)
275 if (creature == wolftype)
282 int Person::getLandhard()
284 if (creature == rabbittype)
286 if (creature == wolftype)
287 return wolflandhardanim;
294 * Person::DoAnimations
297 SolidHitBonus(int playerid)
299 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
300 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
302 award_bonus(playerid, solidhit);
306 * spawns blood effects
308 void Person::DoBlood(float howmuch, int which)
310 // FIXME: should abstract out inputs
311 static int bleedxint, bleedyint;
313 if (bloodtoggle && tutoriallevel != 1) {
314 if (bleeding <= 0 && spurt) {
316 for (int i = 0; i < 3; i++) {
317 // emit blood particles
319 if (!skeleton.free) {
321 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
324 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
327 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
329 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
331 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
332 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
334 if (!skeleton.free) {
335 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
336 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
339 if (Random() % 2 == 0) // 50% chance
340 for (int i = 0; i < 3; i++) {
341 if (Random() % 2 != 0) {
342 // emit teeth particles
345 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
346 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
349 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
350 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
354 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
356 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
358 Sprite::setLastSpriteSpecial(3); // sets it to teeth
363 // FIXME: manipulating attributes
364 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
367 if (creature == rabbittype)
368 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) {
369 bleedxint = abs(Random() % 512);
370 bleedyint = abs(Random() % 512);
372 if (creature == wolftype)
373 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) {
374 bleedxint = abs(Random() % 512);
375 bleedyint = abs(Random() % 512);
379 bleedy /= realtexdetail;
380 bleedx /= realtexdetail;
381 direction = abs(Random() % 2) * 2 - 1;
390 * spawns big blood effects and ???
391 * modifies character's skin texture
393 void Person::DoBloodBig(float howmuch, int which)
395 static int bleedxint, bleedyint, i, j;
397 if (howmuch && id == 0)
400 if (tutoriallevel != 1 || id == 0)
401 if (aitype != playercontrolled && howmuch > 0) {
405 // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
406 if (creature == wolftype) {
407 int i = abs(Random() % 2);
409 whichsound = snarlsound;
411 whichsound = snarl2sound;
412 envsound[numenvsounds] = coords;
413 envsoundvol[numenvsounds] = 16;
414 envsoundlife[numenvsounds] = .4;
417 if (creature == rabbittype) {
418 int i = abs(Random() % 2);
420 whichsound = rabbitpainsound;
421 if (i == 1 && howmuch >= 2)
422 whichsound = rabbitpain1sound;
423 envsound[numenvsounds] = coords;
424 envsoundvol[numenvsounds] = 16;
425 envsoundlife[numenvsounds] = .4;
429 if (whichsound != -1)
430 emit_sound_at(whichsound, coords);
433 if (id == 0 && howmuch > 0) {
434 // FIXME: manipulating attributes
442 if (bloodtoggle && decals && tutoriallevel != 1) {
443 if (bleeding <= 0 && spurt) {
445 for (int i = 0; i < 3; i++) {
446 // emit blood particles
447 // FIXME: copypaste from above
449 if (!skeleton.free) {
451 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
454 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
457 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
459 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
461 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
462 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
464 if (!skeleton.free) {
465 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
466 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
471 // weird texture manipulation code follows.
472 // looks like this is painting blood onto the character's skin texture
473 // FIXME: surely there's a better way
475 int offsetx = 0, offsety = 0;
477 offsety = Random() % 40;
478 offsetx = abs(Random() % 60);
480 if (which == 190 || which == 185) {
481 offsety = Random() % 40;
482 offsetx = abs(Random() % 100) - 20;
485 offsety = Random() % 10;
486 offsetx = Random() % 10;
489 offsety = Random() % 20;
490 offsetx = Random() % 20;
492 if (which == 220 || which == 215) {
502 if (creature == rabbittype)
503 for (i = 0; i < 512; i++) {
504 for (j = 0; j < 512; j++) {
505 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
506 if (i < startx) startx = i;
507 if (j < starty) starty = j;
508 if (i > endx) endx = i;
509 if (j > endy) endy = j;
513 if (creature == wolftype)
514 for (i = 0; i < 512; i++) {
515 for (j = 0; j < 512; j++) {
516 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
517 if (i < startx) startx = i;
518 if (j < starty) starty = j;
519 if (i > endx) endx = i;
520 if (j > endy) endy = j;
530 if (startx < 0) startx = 0;
531 if (starty < 0) starty = 0;
532 if (endx > 512 - 1) endx = 512 - 1;
533 if (endy > 512 - 1) endy = 512 - 1;
534 if (endx < startx) endx = startx;
535 if (endy < starty) endy = starty;
537 startx /= realtexdetail;
538 starty /= realtexdetail;
539 endx /= realtexdetail;
540 endy /= realtexdetail;
542 int texdetailint = realtexdetail;
544 if (creature == rabbittype)
545 for (i = startx; i < endx; i++) {
546 for (j = starty; j < endy; j++) {
547 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) {
548 color = Random() % 85 + 170;
549 where = i * skeleton.skinsize * 3 + j * 3;
550 if (skeleton.skinText[where + 0] > color / 2)
551 skeleton.skinText[where + 0] = color / 2;
552 skeleton.skinText[where + 1] = 0;
553 skeleton.skinText[where + 2] = 0;
557 if (creature == wolftype)
558 for (i = startx; i < endx; i++) {
559 for (j = starty; j < endy; j++) {
560 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) {
561 color = Random() % 85 + 170;
562 where = i * skeleton.skinsize * 3 + j * 3;
563 if (skeleton.skinText[where + 0] > color / 2)
564 skeleton.skinText[where + 0] = color / 2;
565 skeleton.skinText[where + 1] = 0;
566 skeleton.skinText[where + 2] = 0;
570 skeleton.drawmodel.textureptr.bind();
575 if (creature == rabbittype)
576 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) {
577 bleedxint = abs(Random() % 512);
578 bleedyint = abs(Random() % 512);
580 if (creature == wolftype)
581 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) {
582 bleedxint = abs(Random() % 512);
583 bleedyint = abs(Random() % 512);
585 bleedy = bleedxint + offsetx;
586 bleedx = bleedyint + offsety;
587 bleedy /= realtexdetail;
588 bleedx /= realtexdetail;
593 if (bleedx > skeleton.skinsize - 1)
594 bleedx = skeleton.skinsize - 1;
595 if (bleedy > skeleton.skinsize - 1)
596 bleedy = skeleton.skinsize - 1;
597 direction = abs(Random() % 2) * 2 - 1;
600 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
601 deathbleeding += bleeding;
602 bloodloss += bleeding * 3;
604 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
605 if (abs(Random() % 2) == 0) {
606 aitype = gethelptype;
609 aitype = attacktypecutoff;
617 * similar to DoBloodBig
619 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
623 static XYZ startpoint, endpoint, colpoint, movepoint;
624 static float rotationpoint;
626 static XYZ p1, p2, p3, p0;
630 float coordsx, coordsy;
633 if (bloodtoggle && decals && tutoriallevel != 1) {
636 where = DoRotation(where, 0, -yaw, 0);
644 // ray testing for a tri in the character model
645 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
646 if (whichtri != -1) {
647 // low level geometry math
649 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
650 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
651 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
653 CrossProduct(p2-p1,p3-p1,&N);
654 CrossProduct(p0-p1,p3-p1,&temp);
655 s = dotproduct(&temp,&N)/findLength(&N);
656 CrossProduct(p2-p1,p1-p0,&temp);
657 t = dotproduct(&temp,&N)/findLength(&N);
660 bary.x = distsq(&p0, &p1);
661 bary.y = distsq(&p0, &p2);
662 bary.z = distsq(&p0, &p3);
664 total = bary.x + bary.y + bary.z;
673 total = bary.x + bary.y + bary.z;
679 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
680 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
681 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
682 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
683 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
684 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
685 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;
686 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;
688 //coordsx=skeleton.drawmodel.Triangles[whichtri].gx[1];
689 //coordsy=skeleton.drawmodel.Triangles[whichtri].gy[1];
691 if (bleeding <= 0 && spurt) {
693 for (int i = 0; i < 3; i++) {
694 // emit blood particles
695 // FIXME: more copypaste code
697 if (!skeleton.free) {
699 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
702 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
705 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
707 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
709 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
710 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
712 if (!skeleton.free) {
713 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
714 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
719 // texture manipulation follows
721 int offsetx = 0, offsety = 0;
722 offsetx = (1 + coordsy) * 512 - 291;
723 offsety = coordsx * 512 - 437;
730 if (creature == rabbittype)
731 for (i = 0; i < 512; i++) {
732 for (j = 0; j < 512; j++) {
733 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
734 if (i < startx) startx = i;
735 if (j < starty) starty = j;
736 if (i > endx) endx = i;
737 if (j > endy) endy = j;
741 if (creature == wolftype)
742 for (i = 0; i < 512; i++) {
743 for (j = 0; j < 512; j++) {
744 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
745 if (i < startx) startx = i;
746 if (j < starty) starty = j;
747 if (i > endx) endx = i;
748 if (j > endy) endy = j;
757 if (startx < 0) startx = 0;
758 if (starty < 0) starty = 0;
759 if (endx > 512 - 1) endx = 512 - 1;
760 if (endy > 512 - 1) endy = 512 - 1;
761 if (endx < startx) endx = startx;
762 if (endy < starty) endy = starty;
764 startx /= realtexdetail;
765 starty /= realtexdetail;
766 endx /= realtexdetail;
767 endy /= realtexdetail;
769 int texdetailint = realtexdetail;
771 if (creature == rabbittype)
772 for (i = startx; i < endx; i++) {
773 for (j = starty; j < endy; j++) {
774 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) {
775 color = Random() % 85 + 170;
776 where = i * skeleton.skinsize * 3 + j * 3;
777 if (skeleton.skinText[where + 0] > color / 2)
778 skeleton.skinText[where + 0] = color / 2;
779 skeleton.skinText[where + 1] = 0;
780 skeleton.skinText[where + 2] = 0;
781 } 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) {
782 color = Random() % 85 + 170;
783 where = i * skeleton.skinsize * 3 + j * 3;
784 if (skeleton.skinText[where + 0] > color / 2)
785 skeleton.skinText[where + 0] = color / 2;
786 skeleton.skinText[where + 1] = 0;
787 skeleton.skinText[where + 2] = 0;
791 if (creature == wolftype)
792 for (i = startx; i < endx; i++) {
793 for (j = starty; j < endy; j++) {
794 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) {
795 color = Random() % 85 + 170;
796 where = i * skeleton.skinsize * 3 + j * 3;
797 if (skeleton.skinText[where + 0] > color / 2)
798 skeleton.skinText[where + 0] = color / 2;
799 skeleton.skinText[where + 1] = 0;
800 skeleton.skinText[where + 2] = 0;
801 } 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) {
802 color = Random() % 85 + 170;
803 where = i * skeleton.skinsize * 3 + j * 3;
804 if (skeleton.skinText[where + 0] > color / 2)
805 skeleton.skinText[where + 0] = color / 2;
806 skeleton.skinText[where + 1] = 0;
807 skeleton.skinText[where + 2] = 0;
811 skeleton.drawmodel.textureptr.bind();
814 bleedy = (1 + coordsy) * 512;
815 bleedx = coordsx * 512;
816 bleedy /= realtexdetail;
817 bleedx /= realtexdetail;
822 if (bleedx > skeleton.skinsize - 1)
823 bleedx = skeleton.skinsize - 1;
824 if (bleedy > skeleton.skinsize - 1)
825 bleedy = skeleton.skinsize - 1;
826 direction = abs(Random() % 2) * 2 - 1;
831 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
832 deathbleeding += bleeding;
833 bloodloss += bleeding * 3;
835 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
836 if (abs(Random() % 2) == 0) {
837 aitype = gethelptype;
840 aitype = attacktypecutoff;
851 * guessing this performs a reversal
853 void Person::Reverse()
855 if (!((victim->aitype == playercontrolled
857 || staggerdelay <= 0)
858 && victim->animTarget != jumpupanim
859 && victim->animTarget != jumpdownanim
860 && (tutoriallevel != 1 || cananger)
864 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
865 && (victim->id != 0 || difficulty >= 2)
866 && (creature != wolftype || victim->creature == wolftype))
869 if (animTarget == sweepanim) {
870 animTarget = sweepreversedanim;
871 animCurrent = sweepreversedanim;
872 victim->animCurrent = sweepreversalanim;
873 victim->animTarget = sweepreversalanim;
875 if (animTarget == spinkickanim) {
876 animTarget = spinkickreversedanim;
877 animCurrent = spinkickreversedanim;
878 victim->animCurrent = spinkickreversalanim;
879 victim->animTarget = spinkickreversalanim;
881 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
882 if (animTarget == rabbittacklinganim) {
885 victim->frameCurrent = 6;
886 victim->frameTarget = 7;
888 animTarget = upunchreversedanim;
889 animCurrent = upunchreversedanim;
890 victim->animCurrent = upunchreversalanim;
891 victim->animTarget = upunchreversalanim;
893 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
894 if (victim->weaponactive != -1) {
895 victim->throwtogglekeydown = 1;
896 weapons[victim->weaponids[0]].owner = -1;
897 weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
898 if (weapons[victim->weaponids[0]].velocity.x == 0)
899 weapons[victim->weaponids[0]].velocity.x = .1;
900 weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
901 weapons[victim->weaponids[0]].missed = 1;
902 weapons[victim->weaponids[0]].freetime = 0;
903 weapons[victim->weaponids[0]].firstfree = 1;
904 weapons[victim->weaponids[0]].physics = 1;
905 victim->num_weapons--;
906 if (victim->num_weapons) {
907 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
908 if (victim->weaponstuck == victim->num_weapons)
909 victim->weaponstuck = 0;
912 victim->weaponactive = -1;
913 for (unsigned j = 0; j < Person::players.size(); j++) {
914 Person::players[j]->wentforweapon = 0;
918 animTarget = staffhitreversedanim;
919 animCurrent = staffhitreversedanim;
920 victim->animCurrent = staffhitreversalanim;
921 victim->animTarget = staffhitreversalanim;
923 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
924 if (victim->weaponactive != -1) {
925 victim->throwtogglekeydown = 1;
926 weapons[victim->weaponids[0]].owner = -1;
927 weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
928 if (weapons[victim->weaponids[0]].velocity.x == 0)
929 weapons[victim->weaponids[0]].velocity.x = .1;
930 weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
931 weapons[victim->weaponids[0]].missed = 1;
932 weapons[victim->weaponids[0]].freetime = 0;
933 weapons[victim->weaponids[0]].firstfree = 1;
934 weapons[victim->weaponids[0]].physics = 1;
935 victim->num_weapons--;
936 if (victim->num_weapons) {
937 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
938 if (victim->weaponstuck == victim->num_weapons)
939 victim->weaponstuck = 0;
942 victim->weaponactive = -1;
943 for (unsigned j = 0; j < Person::players.size(); j++) {
944 Person::players[j]->wentforweapon = 0;
947 animTarget = staffspinhitreversedanim;
948 animCurrent = staffspinhitreversedanim;
949 victim->animCurrent = staffspinhitreversalanim;
950 victim->animTarget = staffspinhitreversalanim;
952 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
953 if (victim->weaponactive != -1) {
954 victim->throwtogglekeydown = 1;
955 weapons[victim->weaponids[0]].owner = -1;
956 weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
957 if (weapons[victim->weaponids[0]].velocity.x == 0)
958 weapons[victim->weaponids[0]].velocity.x = .1;
959 weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
960 weapons[victim->weaponids[0]].missed = 1;
961 weapons[victim->weaponids[0]].freetime = 0;
962 weapons[victim->weaponids[0]].firstfree = 1;
963 weapons[victim->weaponids[0]].physics = 1;
964 victim->num_weapons--;
965 if (victim->num_weapons) {
966 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
967 if (victim->weaponstuck == victim->num_weapons)
968 victim->weaponstuck = 0;
971 victim->weaponactive = -1;
972 for (unsigned j = 0; j < Person::players.size(); j++) {
973 Person::players[j]->wentforweapon = 0;
976 animTarget = swordslashreversedanim;
977 animCurrent = swordslashreversedanim;
978 victim->animCurrent = swordslashreversalanim;
979 victim->animTarget = swordslashreversalanim;
981 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
982 if (victim->weaponactive != -1) {
983 victim->throwtogglekeydown = 1;
984 weapons[victim->weaponids[0]].owner = -1;
985 weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
986 if (weapons[victim->weaponids[0]].velocity.x == 0)
987 weapons[victim->weaponids[0]].velocity.x = .1;
988 weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
989 weapons[victim->weaponids[0]].missed = 1;
990 weapons[victim->weaponids[0]].freetime = 0;
991 weapons[victim->weaponids[0]].firstfree = 1;
992 weapons[victim->weaponids[0]].physics = 1;
993 victim->num_weapons--;
994 if (victim->num_weapons) {
995 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
996 if (victim->weaponstuck == victim->num_weapons)
997 victim->weaponstuck = 0;
1000 victim->weaponactive = -1;
1001 for (unsigned j = 0; j < Person::players.size(); j++) {
1002 Person::players[j]->wentforweapon = 0;
1005 animTarget = knifeslashreversedanim;
1006 animCurrent = knifeslashreversedanim;
1007 victim->animCurrent = knifeslashreversalanim;
1008 victim->animTarget = knifeslashreversalanim;
1010 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1011 victim->targettilt2 = targettilt2;
1012 victim->frameCurrent = frameCurrent;
1013 victim->frameTarget = frameTarget;
1014 victim->target = target;
1015 victim->velocity = 0;
1016 victim->oldcoords = victim->coords;
1017 victim->coords = coords;
1018 victim->targetyaw = targetyaw;
1019 victim->yaw = targetyaw;
1020 victim->victim = this->shared_from_this();
1022 if (animTarget == winduppunchanim) {
1023 animTarget = winduppunchblockedanim;
1024 victim->animTarget = blockhighleftanim;
1025 victim->frameTarget = 1;
1026 victim->target = .5;
1027 victim->victim = this->shared_from_this();
1028 victim->targetyaw = targetyaw + 180;
1030 if (animTarget == wolfslapanim) {
1031 animTarget = winduppunchblockedanim;
1032 victim->animTarget = blockhighleftanim;
1033 victim->frameTarget = 1;
1034 victim->target = .5;
1035 victim->victim = this->shared_from_this();
1036 victim->targetyaw = targetyaw + 180;
1038 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1039 animTarget = swordslashparriedanim;
1040 parriedrecently = .4;
1041 victim->parriedrecently = 0;
1042 victim->animTarget = swordslashparryanim;
1043 victim->frameTarget = 1;
1044 victim->target = .5;
1045 victim->victim = this->shared_from_this();
1046 victim->targetyaw = targetyaw + 180;
1048 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1049 if (victim->weaponactive != -1) {
1050 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1051 if (weapons[victim->weaponids[0]].getType() == staff)
1052 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1053 if (weapons[weaponids[0]].getType() == staff)
1054 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1055 emit_sound_at(swordstaffsound, victim->coords);
1057 emit_sound_at(metalhitsound, victim->coords);
1061 victim->Puff(righthand);
1063 victim->frameTarget = 0;
1064 victim->animTarget = staggerbackhighanim;
1065 victim->targetyaw = targetyaw + 180;
1067 weapons[victim->weaponids[0]].owner = -1;
1068 aim = DoRotation(facing, 0, 90, 0) * 21;
1070 weapons[victim->weaponids[0]].velocity = aim * -.2;
1071 weapons[victim->weaponids[0]].tipvelocity = aim;
1072 weapons[victim->weaponids[0]].missed = 1;
1073 weapons[victim->weaponids[0]].hitsomething = 0;
1074 weapons[victim->weaponids[0]].freetime = 0;
1075 weapons[victim->weaponids[0]].firstfree = 1;
1076 weapons[victim->weaponids[0]].physics = 1;
1077 victim->num_weapons--;
1078 if (victim->num_weapons) {
1079 victim->weaponids[0] = victim->weaponids[num_weapons];
1080 if (victim->weaponstuck == victim->num_weapons)
1081 victim->weaponstuck = 0;
1083 victim->weaponactive = -1;
1084 for (unsigned i = 0; i < Person::players.size(); i++) {
1085 Person::players[i]->wentforweapon = 0;
1089 if (abs(Random() % 20) == 0) {
1090 if (weaponactive != -1) {
1091 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1092 if (weapons[victim->weaponids[0]].getType() == staff)
1093 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1094 if (weapons[weaponids[0]].getType() == staff)
1095 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1097 emit_sound_at(swordstaffsound, coords);
1099 emit_sound_at(metalhitsound, coords);
1107 animTarget = staggerbackhighanim;
1108 targetyaw = targetyaw + 180;
1110 weapons[weaponids[0]].owner = -1;
1111 aim = DoRotation(facing, 0, 90, 0) * 21;
1113 weapons[weaponids[0]].velocity = aim * -.2;
1114 weapons[weaponids[0]].tipvelocity = aim;
1115 weapons[weaponids[0]].hitsomething = 0;
1116 weapons[weaponids[0]].missed = 1;
1117 weapons[weaponids[0]].freetime = 0;
1118 weapons[weaponids[0]].firstfree = 1;
1119 weapons[weaponids[0]].physics = 1;
1122 weaponids[0] = weaponids[num_weapons];
1123 if (weaponstuck == num_weapons)
1127 for (unsigned i = 0; i < Person::players.size(); i++) {
1128 Person::players[i]->wentforweapon = 0;
1135 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1136 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1137 victim->animTarget = dodgebackanim;
1138 victim->frameTarget = 0;
1142 rotatetarget = coords - victim->coords;
1143 Normalise(&rotatetarget);
1144 victim->targetyaw = -asin(0 - rotatetarget.x);
1145 victim->targetyaw *= 360 / 6.28;
1146 if (rotatetarget.z < 0)
1147 victim->targetyaw = 180 - victim->targetyaw;
1149 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1151 victim->lastattack3 = victim->lastattack2;
1152 victim->lastattack2 = victim->lastattack;
1153 victim->lastattack = victim->animTarget;
1155 victim->animTarget = sweepanim;
1156 victim->frameTarget = 0;
1160 rotatetarget = coords - victim->coords;
1161 Normalise(&rotatetarget);
1162 victim->targetyaw = -asin(0 - rotatetarget.x);
1163 victim->targetyaw *= 360 / 6.28;
1164 if (rotatetarget.z < 0)
1165 victim->targetyaw = 180 - victim->targetyaw;
1167 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1169 victim->lastattack3 = victim->lastattack2;
1170 victim->lastattack2 = victim->lastattack;
1171 victim->lastattack = victim->animTarget;
1176 victim->velocity = 0;
1178 if (aitype != playercontrolled)
1180 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1182 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1184 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1187 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1194 void Person::DoDamage(float howmuch)
1196 // subtract health (temporary?)
1197 if (tutoriallevel != 1)
1198 damage += howmuch / power;
1201 damagedealt += howmuch / power;
1203 damagetaken += howmuch / power;
1206 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1209 if (tutoriallevel != 1)
1210 permanentdamage += howmuch / 2 / power;
1211 if (tutoriallevel != 1)
1212 superpermanentdamage += howmuch / 4 / power;
1214 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1216 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1220 camerashake += howmuch / 100;
1221 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1222 blackout = damage / damagetolerance;
1227 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1228 aitype = attacktypecutoff;
1229 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1230 if (abs(Random() % 2) == 0) {
1231 aitype = gethelptype;
1234 aitype = attacktypecutoff;
1238 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1241 for (int i = 0; i < skeleton.num_joints; i++) {
1243 flatvelocity2 = velocity;
1245 flatvelocity2 = skeleton.joints[i].velocity;
1247 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1249 flatfacing2 = skeleton.joints[i].position * scale + coords;
1250 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1251 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1252 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1253 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1254 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1255 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1258 emit_sound_at(splattersound, coords);
1263 if (!dead && creature == wolftype) {
1264 award_bonus(0, Wolfbonus);
1271 if (tutoriallevel != 1 || id == 0)
1272 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1273 int whichsound = -1;
1275 if (creature == wolftype) {
1276 int i = abs(Random() % 2);
1278 whichsound = snarlsound;
1280 whichsound = snarl2sound;
1281 envsound[numenvsounds] = coords;
1282 envsoundvol[numenvsounds] = 16;
1283 envsoundlife[numenvsounds] = .4;
1286 if (creature == rabbittype) {
1287 int i = abs(Random() % 2);
1289 whichsound = rabbitpainsound;
1290 if (i == 1 && damage > damagetolerance)
1291 whichsound = rabbitpain1sound;
1292 envsound[numenvsounds] = coords;
1293 envsoundvol[numenvsounds] = 16;
1294 envsoundlife[numenvsounds] = .4;
1298 if (whichsound != -1) {
1299 emit_sound_at(whichsound, coords);
1306 * calculate/animate head facing direction?
1308 void Person::DoHead()
1310 static XYZ rotatearound;
1312 static float lookspeed = 500;
1314 if (!freeze && !winfreeze) {
1317 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1318 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1320 while (targetheadyaw > 180)targetheadyaw -= 360;
1321 while (targetheadyaw < -180)targetheadyaw += 360;
1323 if (targetheadyaw > 160)
1324 targetheadpitch = targetheadpitch * -1;
1325 if (targetheadyaw < -160)
1326 targetheadpitch = targetheadpitch * -1;
1327 if (targetheadyaw > 160)
1328 targetheadyaw = targetheadyaw - 180;
1329 if (targetheadyaw < -160)
1330 targetheadyaw = targetheadyaw + 180;
1332 if (targetheadpitch > 120)
1333 targetheadpitch = 120;
1334 if (targetheadpitch < -120)
1335 targetheadpitch = -120;
1336 if (targetheadyaw > 120)
1337 targetheadyaw = 120;
1338 if (targetheadyaw < -120)
1339 targetheadyaw = -120;
1342 targetheadpitch = 0;
1344 if (targetheadyaw > 80)
1346 if (targetheadyaw < -80)
1347 targetheadyaw = -80;
1348 if (targetheadpitch > 50)
1349 targetheadpitch = 50;
1350 if (targetheadpitch < -50)
1351 targetheadpitch = -50;
1354 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1355 headyaw = targetheadyaw;
1356 else if (headyaw > targetheadyaw) {
1357 headyaw -= multiplier * lookspeed;
1358 } else if (headyaw < targetheadyaw) {
1359 headyaw += multiplier * lookspeed;
1362 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1363 headpitch = targetheadpitch;
1364 else if (headpitch > targetheadpitch) {
1365 headpitch -= multiplier * lookspeed / 2;
1366 } else if (headpitch < targetheadpitch) {
1367 headpitch += multiplier * lookspeed / 2;
1370 rotatearound = jointPos(neck);
1371 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1375 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1376 facing = DoRotation(facing, headpitch * .4, 0, 0);
1377 facing = DoRotation(facing, 0, headyaw * .4, 0);
1380 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1381 facing = DoRotation(facing, headpitch * .8, 0, 0);
1382 facing = DoRotation(facing, 0, headyaw * .8, 0);
1385 if (animTarget == walkanim) {
1386 facing = DoRotation(facing, headpitch * .6, 0, 0);
1387 facing = DoRotation(facing, 0, headyaw * .6, 0);
1390 skeleton.specialforward[0] = facing;
1391 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1392 for (int i = 0; i < skeleton.num_muscles; i++) {
1393 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1394 skeleton.FindRotationMuscle(i, animTarget);
1401 * ragdolls character?
1403 void Person::RagDoll(bool checkcollision)
1408 if (!skeleton.free) {
1411 if (id == 0 && isFlip())
1418 facing = DoRotation(facing, 0, yaw, 0);
1420 skeleton.freetime = 0;
1422 skeleton.longdead = 0;
1425 skeleton.broken = 0;
1426 skeleton.spinny = 1;
1428 skeleton.freefall = 1;
1430 if (!isnormal(velocity.x)) velocity.x = 0;
1431 if (!isnormal(velocity.y)) velocity.y = 0;
1432 if (!isnormal(velocity.z)) velocity.z = 0;
1433 if (!isnormal(yaw)) yaw = 0;
1434 if (!isnormal(coords.x)) coords = 0;
1435 if (!isnormal(tilt)) tilt = 0;
1436 if (!isnormal(tilt2)) tilt2 = 0;
1438 for (int i = 0; i < skeleton.num_joints; i++) {
1439 skeleton.joints[i].delay = 0;
1440 skeleton.joints[i].locked = 0;
1441 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1442 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1443 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1444 skeleton.joints[i].position.y += .1;
1445 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1446 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1449 for (int i = 0; i < skeleton.num_joints; i++) {
1450 skeleton.joints[i].velocity = 0;
1451 skeleton.joints[i].velchange = 0;
1453 skeleton.DoConstraints(&coords, &scale);
1454 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1455 skeleton.DoConstraints(&coords, &scale);
1456 skeleton.DoConstraints(&coords, &scale);
1457 skeleton.DoConstraints(&coords, &scale);
1458 skeleton.DoConstraints(&coords, &scale);
1461 speed = animation[animTarget].speed[frameTarget] * 2;
1462 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1463 speed = animation[animCurrent].speed[frameCurrent] * 2;
1466 speed = transspeed * 2;
1470 for (int i = 0; i < skeleton.num_joints; i++) {
1471 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1472 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);
1474 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1475 change.x = (float)(Random() % 100) / 100;
1476 change.y = (float)(Random() % 100) / 100;
1477 change.z = (float)(Random() % 100) / 100;
1478 skeleton.joints[i].velocity += change;
1479 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1481 change.x = (float)(Random() % 100) / 100;
1482 change.y = (float)(Random() % 100) / 100;
1483 change.z = (float)(Random() % 100) / 100;
1484 skeleton.joints[i].velchange += change;
1485 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1488 if (checkcollision) {
1495 for (j = 0; j < skeleton.num_joints; j++) {
1496 average += skeleton.joints[j].position;
1500 coords += average * scale;
1501 for (j = 0; j < skeleton.num_joints; j++) {
1502 skeleton.joints[j].position -= average;
1505 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1506 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1507 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1508 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1509 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1512 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1513 coords.x = lowpoint.x;
1514 coords.z = lowpoint.z;
1523 for (int i = 0; i < skeleton.num_joints; i++) {
1524 velocity += skeleton.joints[i].velocity * scale;
1526 velocity /= skeleton.num_joints;
1529 if (Random() % 2 == 0) {
1530 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1531 weapons[weaponids[0]].owner = -1;
1532 weapons[weaponids[0]].hitsomething = 0;
1533 weapons[weaponids[0]].velocity = jointVel(righthand) * scale * -.3;
1534 weapons[weaponids[0]].velocity.x += .01;
1535 weapons[weaponids[0]].tipvelocity = jointVel(righthand) * scale;
1536 weapons[weaponids[0]].missed = 1;
1537 weapons[weaponids[0]].freetime = 0;
1538 weapons[weaponids[0]].firstfree = 1;
1539 weapons[weaponids[0]].physics = 1;
1542 weaponids[0] = weaponids[num_weapons];
1543 if (weaponstuck == num_weapons)
1547 for (unsigned i = 0; i < Person::players.size(); i++) {
1548 Person::players[i]->wentforweapon = 0;
1553 animTarget = bounceidleanim;
1554 animCurrent = bounceidleanim;
1564 void Person::FootLand(int which, float opacity)
1566 static XYZ terrainlight;
1567 static XYZ footvel, footpoint;
1568 if (opacity >= 1 || skiddelay <= 0)
1572 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1574 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1575 //footpoint.y=coords.y;
1576 if (distsq(&footpoint, &viewer))
1577 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1578 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1579 footvel = velocity / 5;
1583 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1585 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1586 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1587 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1588 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1589 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1590 if (opacity >= 1 || detail == 2)
1592 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1593 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1594 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1595 footvel = velocity / 5;
1599 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1601 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1602 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1603 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1604 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1605 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1606 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1607 footvel = velocity / 5;
1611 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1613 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1614 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1615 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1616 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1617 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1618 if (opacity >= 1 || detail == 2)
1620 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1621 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1622 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1623 footvel = velocity / 5;
1627 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1629 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1630 //footpoint.y=coords.y;
1631 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1632 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1637 * make a puff effect at a body part (dust effect?)
1639 void Person::Puff(int whichlabel)
1641 static XYZ footvel, footpoint;
1644 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1645 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1649 * I think I added this in an attempt to clean up code
1651 void Person::setAnimation(int animation)
1653 animTarget = animation;
1662 void Person::DoAnimations()
1664 if (!skeleton.free) {
1665 static float oldtarget;
1667 if (isIdle() && animCurrent != getIdle())
1668 normalsupdatedelay = 0;
1670 if (animTarget == tempanim || animCurrent == tempanim) {
1671 animation[tempanim] = tempanimation;
1673 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1679 vel[0] = velocity.x;
1680 vel[1] = velocity.y;
1681 vel[2] = velocity.z;
1684 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1685 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1687 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1689 if (!crouchkeydown && velocity.y >= -15)
1692 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1697 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1699 if (normaldotproduct(targfacing, velocity) >= -.3)
1700 animTarget = flipanim;
1702 animTarget = backflipanim;
1703 crouchtogglekeydown = 1;
1711 if (animation[animTarget].attack != reversed)
1713 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1714 crouchtogglekeydown = 0;
1715 if (aitype == playercontrolled)
1718 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1721 crouchtogglekeydown = 1;
1725 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1727 normalsupdatedelay = 0;
1731 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1733 emit_sound_at(fireendsound, coords);
1734 pause_sound(stream_firesound);
1738 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1739 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1741 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1742 if (normaldotproduct(victim->facing, facing) > 0)
1743 victim->animTarget = rabbittackledbackanim;
1745 victim->animTarget = rabbittackledfrontanim;
1746 victim->frameTarget = 2;
1749 victim->targetyaw = yaw;
1750 if (victim->aitype == gethelptype)
1751 victim->DoDamage(victim->damagetolerance - victim->damage);
1752 //victim->DoDamage(30);
1753 if (creature == wolftype) {
1755 emit_sound_at(clawslicesound, victim->coords);
1757 victim->DoBloodBig(1 / victim->armorhead, 210);
1759 award_bonus(id, TackleBonus,
1760 victim->aitype == gethelptype ? 50 : 0);
1764 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1765 if (weapons[weaponids[0]].getType() == knife) {
1766 if (weaponactive == -1)
1768 else if (weaponactive == 0)
1771 if (weaponactive == -1) {
1772 emit_sound_at(knifesheathesound, coords);
1774 if (weaponactive != -1) {
1775 emit_sound_at(knifedrawsound, coords, 128);
1778 drawtogglekeydown = 1;
1781 if (tutoriallevel != 1 || id == 0)
1782 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1785 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1786 if (animation[animTarget].label[frameTarget] == 1)
1787 whichsound = footstepsound;
1789 whichsound = footstepsound2;
1790 if (animation[animTarget].label[frameTarget] == 1)
1792 if (animation[animTarget].label[frameTarget] == 2)
1794 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1800 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1801 if (animation[animTarget].label[frameTarget] == 1)
1802 whichsound = footstepsound3;
1804 whichsound = footstepsound4;
1808 if (animation[animTarget].label[frameTarget] == 1)
1809 whichsound = footstepsound3;
1811 whichsound = footstepsound4;
1813 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1814 if (animation[animTarget].attack != neutral) {
1815 unsigned r = abs(Random() % 3);
1817 whichsound = lowwhooshsound;
1819 whichsound = midwhooshsound;
1821 whichsound = highwhooshsound;
1823 if (animation[animTarget].attack == neutral)
1824 whichsound = movewhooshsound;
1825 } else if (animation[animTarget].label[frameTarget] == 4)
1826 whichsound = knifeswishsound;
1827 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1828 whichsound = landsound2;
1830 emit_sound_at(whichsound, coords, 256.);
1833 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1834 envsound[numenvsounds] = coords;
1835 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1836 envsoundvol[numenvsounds] = 15;
1838 envsoundvol[numenvsounds] = 6;
1839 envsoundlife[numenvsounds] = .4;
1843 if (animation[animTarget].label[frameTarget] == 3) {
1845 emit_sound_at(whichsound, coords, 128.);
1850 if (tutoriallevel != 1 || id == 0)
1851 if (speechdelay <= 0)
1852 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1853 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1854 int whichsound = -1;
1855 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1856 if (animation[animTarget].attack != neutral) {
1857 unsigned r = abs(Random() % 4);
1858 if (creature == rabbittype) {
1859 if (r == 0) whichsound = rabbitattacksound;
1860 if (r == 1) whichsound = rabbitattack2sound;
1861 if (r == 2) whichsound = rabbitattack3sound;
1862 if (r == 3) whichsound = rabbitattack4sound;
1864 if (creature == wolftype) {
1865 if (r == 0) whichsound = barksound;
1866 if (r == 1) whichsound = bark2sound;
1867 if (r == 2) whichsound = bark3sound;
1868 if (r == 3) whichsound = barkgrowlsound;
1874 if (whichsound != -1) {
1875 emit_sound_at(whichsound, coords);
1881 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
1887 currentoffset = targetoffset;
1888 frameTarget = frameCurrent;
1889 animCurrent = animTarget;
1892 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1893 for (unsigned i = 0; i < weapons.size(); i++) {
1894 if (weapons[i].owner == -1)
1895 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
1896 if (distsq(&coords, &weapons[i].position) >= 1) {
1897 if (weapons[i].getType() != staff) {
1898 emit_sound_at(knifedrawsound, coords, 128.);
1902 weapons[i].owner = id;
1903 if (num_weapons > 0) {
1904 weaponids[num_weapons] = weaponids[0];
1913 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1914 for (unsigned i = 0; i < weapons.size(); i++) {
1915 bool willwork = true;
1916 if (weapons[i].owner != -1)
1917 if (Person::players[weapons[i].owner]->weaponstuck != -1)
1918 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
1919 if (Person::players[weapons[i].owner]->num_weapons > 1)
1921 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
1922 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
1923 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
1924 bool fleshstuck = false;
1925 if (weapons[i].owner != -1)
1926 if (victim->weaponstuck != -1) {
1927 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1932 emit_sound_at(fleshstabremovesound, coords, 128.);
1934 if (weapons[i].getType() != staff) {
1935 emit_sound_at(knifedrawsound, coords, 128.);
1939 if (weapons[i].owner != -1) {
1941 victim = Person::players[weapons[i].owner];
1942 if (victim->num_weapons == 1)
1943 victim->num_weapons = 0;
1945 victim->num_weapons = 1;
1947 //victim->weaponactive=-1;
1948 victim->skeleton.longdead = 0;
1949 victim->skeleton.free = 1;
1950 victim->skeleton.broken = 0;
1952 for (int j = 0; j < victim->skeleton.num_joints; j++) {
1953 victim->skeleton.joints[j].velchange = 0;
1954 victim->skeleton.joints[j].locked = 0;
1960 Normalise(&relative);
1961 XYZ footvel, footpoint;
1963 footpoint = weapons[i].position;
1964 if (victim->weaponstuck != -1) {
1965 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1967 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
1968 weapons[i].bloody = 2;
1969 weapons[i].blooddrip = 5;
1970 victim->weaponstuck = -1;
1973 if (victim->num_weapons > 0) {
1974 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
1975 victim->weaponstuck = 0;
1976 if (victim->weaponids[0] == int(i))
1977 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1980 victim->jointVel(abdomen) += relative * 6;
1981 victim->jointVel(neck) += relative * 6;
1982 victim->jointVel(rightshoulder) += relative * 6;
1983 victim->jointVel(leftshoulder) += relative * 6;
1985 weapons[i].owner = id;
1986 if (num_weapons > 0) {
1987 weaponids[num_weapons] = weaponids[0];
1996 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
1997 if (weaponactive == -1)
1999 else if (weaponactive == 0) {
2001 if (num_weapons == 2) {
2003 buffer = weaponids[0];
2004 weaponids[0] = weaponids[1];
2005 weaponids[1] = buffer;
2008 if (weaponactive == -1) {
2009 emit_sound_at(knifesheathesound, coords, 128.);
2011 if (weaponactive != -1) {
2012 emit_sound_at(knifedrawsound, coords, 128.);
2017 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2018 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2019 Normalise(&rotatetarget);
2020 targetyaw = -asin(0 - rotatetarget.x);
2021 targetyaw *= 360 / 6.28;
2022 if (rotatetarget.z < 0)
2023 targetyaw = 180 - targetyaw;
2025 if (animTarget == walljumprightkickanim)
2027 if (animTarget == walljumpleftkickanim)
2033 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2036 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2041 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2042 animTarget = rabbittackleanim;
2044 emit_sound_at(jumpsound, coords);
2052 targetloc = velocity;
2053 Normalise(&targetloc);
2054 targetloc += coords;
2055 for (unsigned i = 0; i < Person::players.size(); i++) {
2057 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2058 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2062 if (closestid != -1)
2063 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2065 victim = Person::players[closestid];
2066 coords = victim->coords;
2067 animCurrent = rabbittacklinganim;
2068 animTarget = rabbittacklinganim;
2072 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2073 rotatetarget = coords - victim->coords;
2074 Normalise(&rotatetarget);
2075 targetyaw = -asin(0 - rotatetarget.x);
2076 targetyaw *= 360 / 6.28;
2077 if (rotatetarget.z < 0)
2078 targetyaw = 180 - targetyaw;
2080 if (animTarget != rabbitrunninganim) {
2081 emit_sound_at(jumpsound, coords, 128.);
2087 float damagemult = 1 * power;
2088 if (creature == wolftype)
2089 damagemult = 2.5 * power;
2091 damagemult /= victim->damagetolerance / 200;
2093 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2094 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2095 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2099 if (Random() % 2 || creature == wolftype) {
2102 if (creature == wolftype)
2105 if (tutoriallevel != 1) {
2106 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2108 if (creature == wolftype) {
2109 emit_sound_at(clawslicesound, victim->coords, 128.);
2111 victim->DoBloodBig(2 / victim->armorhead, 175);
2115 relative = victim->coords - coords;
2117 Normalise(&relative);
2118 relative = DoRotation(relative, 0, -90, 0);
2119 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2120 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2122 victim->jointVel(head) += relative * damagemult * 200;
2125 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2131 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2132 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2136 if (Random() % 2 || creature == wolftype) {
2138 if (creature == wolftype)
2141 emit_sound_at(whooshhitsound, victim->coords);
2142 if (creature == wolftype) {
2143 emit_sound_at(clawslicesound, victim->coords, 128.);
2145 victim->DoBloodBig(2, 175);
2149 relative = victim->coords - coords;
2151 Normalise(&relative);
2153 Normalise(&relative);
2154 relative = DoRotation(relative, 0, 90, 0);
2155 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2156 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2158 victim->jointVel(head) += relative * damagemult * 100;
2161 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2165 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2166 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2172 if (tutoriallevel != 1) {
2173 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2175 if (creature == wolftype) {
2176 emit_sound_at(clawslicesound, victim->coords, 128.);
2178 victim->DoBloodBig(2 / victim->armorhead, 175);
2184 Normalise(&relative);
2185 relative = DoRotation(relative, 0, -90, 0);
2186 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2187 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2189 victim->jointVel(head) += relative * damagemult * 200;
2192 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2194 if (victim->damage > victim->damagetolerance)
2195 award_bonus(id, style);
2201 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2202 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2208 if (tutoriallevel != 1) {
2209 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2211 if (creature == wolftype) {
2212 emit_sound_at(clawslicesound, victim->coords, 128.);
2214 victim->DoBloodBig(2 / victim->armorhead, 175);
2220 Normalise(&relative);
2221 relative = DoRotation(relative, 0, 90, 0);
2222 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2223 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2225 victim->jointVel(head) += relative * damagemult * 200;
2228 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2230 if (victim->damage > victim->damagetolerance)
2231 award_bonus(id, style);
2237 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2238 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2246 emit_sound_at(whooshhitsound, victim->coords);
2249 relative = victim->coords - coords;
2251 Normalise(&relative);
2252 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2253 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2255 victim->jointVel(head) += relative * damagemult * 100;
2258 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2262 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2263 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2267 emit_sound_at(whooshhitsound, victim->coords, 128.);
2269 victim->skeleton.longdead = 0;
2270 victim->skeleton.free = 1;
2271 victim->skeleton.broken = 0;
2272 victim->skeleton.spinny = 1;
2274 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2275 victim->skeleton.joints[i].velchange = 0;
2276 victim->skeleton.joints[i].delay = 0;
2277 victim->skeleton.joints[i].locked = 0;
2278 //victim->skeleton.joints[i].velocity=0;
2284 Normalise(&relative);
2285 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2286 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2287 victim->skeleton.joints[i].position.y += relative.y * .3;
2288 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2289 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2291 victim->Puff(abdomen);
2292 victim->jointVel(abdomen).y = relative.y * 400;
2296 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2297 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2301 if (tutoriallevel != 1) {
2302 emit_sound_at(heavyimpactsound, coords, 128.);
2305 relative = victim->coords - coords;
2307 Normalise(&relative);
2308 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2309 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2311 victim->Puff(abdomen);
2312 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2316 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2317 victim->jointVel(abdomen) += relative * damagemult * 300;
2321 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2322 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2326 if (tutoriallevel != 1) {
2327 emit_sound_at(thudsound, coords);
2330 victim->skeleton.longdead = 0;
2331 victim->skeleton.free = 1;
2332 victim->skeleton.broken = 0;
2333 victim->skeleton.spinny = 1;
2335 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2336 victim->skeleton.joints[i].velchange = 0;
2337 //victim->skeleton.joints[i].delay=0;
2338 victim->skeleton.joints[i].locked = 0;
2341 relative = victim->coords - coords;
2342 Normalise(&relative);
2344 Normalise(&relative);
2345 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2346 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2351 victim->Puff(abdomen);
2352 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2353 victim->jointVel(abdomen) += relative * damagemult * 200;
2362 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2365 if (!victim->skeleton.free)
2369 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2370 emit_sound_at(knifesheathesound, coords, 128.);
2373 if (victim && hasvictim) {
2374 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2376 XYZ where, startpoint, endpoint, movepoint, colpoint;
2377 float rotationpoint;
2379 if (weapons[weaponids[weaponactive]].getType() == knife) {
2380 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2381 where -= victim->coords;
2382 if (!victim->skeleton.free)
2383 where = DoRotation(where, 0, -victim->yaw, 0);
2386 startpoint.y += 100;
2390 if (weapons[weaponids[weaponactive]].getType() == sword) {
2391 where = weapons[weaponids[weaponactive]].position;
2392 where -= victim->coords;
2393 if (!victim->skeleton.free)
2394 where = DoRotation(where, 0, -victim->yaw, 0);
2396 where = weapons[weaponids[weaponactive]].tippoint;
2397 where -= victim->coords;
2398 if (!victim->skeleton.free)
2399 where = DoRotation(where, 0, -victim->yaw, 0);
2402 if (weapons[weaponids[weaponactive]].getType() == staff) {
2403 where = weapons[weaponids[weaponactive]].position;
2404 where -= victim->coords;
2405 if (!victim->skeleton.free)
2406 where = DoRotation(where, 0, -victim->yaw, 0);
2408 where = weapons[weaponids[weaponactive]].tippoint;
2409 where -= victim->coords;
2410 if (!victim->skeleton.free)
2411 where = DoRotation(where, 0, -victim->yaw, 0);
2416 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2418 if (whichtri != -1) {
2419 if (victim->dead != 2) {
2420 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2422 award_bonus(id, FinishedBonus);
2425 weapons[weaponids[weaponactive]].bloody = 2;
2427 victim->skeleton.longdead = 0;
2428 victim->skeleton.free = 1;
2429 victim->skeleton.broken = 0;
2431 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2432 victim->skeleton.joints[i].velchange = 0;
2433 victim->skeleton.joints[i].locked = 0;
2434 //victim->skeleton.joints[i].velocity=0;
2436 emit_sound_at(fleshstabsound, coords, 128);
2439 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2440 weapons[weaponids[weaponactive]].blooddrip += 5;
2441 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2443 if (whichtri == -1) {
2445 emit_sound_at(knifesheathesound, coords, 128.);
2451 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2453 emit_sound_at(knifedrawsound, coords, 128);
2456 if (victim && hasvictim) {
2457 XYZ footvel, footpoint;
2459 emit_sound_at(fleshstabremovesound, coords, 128.);
2462 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2464 if (weapons[weaponids[weaponactive]].getType() == sword) {
2465 XYZ where, startpoint, endpoint, movepoint;
2466 float rotationpoint;
2469 where = weapons[weaponids[weaponactive]].position;
2470 where -= victim->coords;
2471 if (!victim->skeleton.free)
2472 where = DoRotation(where, 0, -victim->yaw, 0);
2474 where = weapons[weaponids[weaponactive]].tippoint;
2475 where -= victim->coords;
2476 if (!victim->skeleton.free)
2477 where = DoRotation(where, 0, -victim->yaw, 0);
2482 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2483 footpoint += victim->coords;
2485 if (whichtri == -1) {
2486 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2489 if (weapons[weaponids[weaponactive]].getType() == staff) {
2490 XYZ where, startpoint, endpoint, movepoint;
2491 float rotationpoint;
2494 where = weapons[weaponids[weaponactive]].position;
2495 where -= victim->coords;
2496 if (!victim->skeleton.free)
2497 where = DoRotation(where, 0, -victim->yaw, 0);
2499 where = weapons[weaponids[weaponactive]].tippoint;
2500 where -= victim->coords;
2501 if (!victim->skeleton.free)
2502 where = DoRotation(where, 0, -victim->yaw, 0);
2507 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2508 footpoint += victim->coords;
2510 if (whichtri == -1) {
2511 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2514 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2516 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2517 victim->skeleton.longdead = 0;
2518 victim->skeleton.free = 1;
2519 victim->skeleton.broken = 0;
2521 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2522 victim->skeleton.joints[i].velchange = 0;
2523 victim->skeleton.joints[i].locked = 0;
2524 //victim->skeleton.joints[i].velocity=0;
2530 Normalise(&relative);
2531 //victim->Puff(abdomen);
2533 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2535 if (victim->bloodloss < victim->damagetolerance) {
2536 victim->bloodloss += 1000;
2540 victim->jointVel(abdomen) += relative * damagemult * 20;
2544 if (!hasvictim && onterrain) {
2545 weapons[weaponids[weaponactive]].bloody = 0;
2546 weapons[weaponids[weaponactive]].blooddrip = 0;
2550 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2551 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2559 if (tutoriallevel != 1) {
2560 emit_sound_at(heavyimpactsound, victim->coords, 128);
2565 relative = victim->coords - coords;
2567 Normalise(&relative);
2568 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2569 victim->skeleton.joints[i].velocity = relative * 30;
2571 victim->jointVel(head) += relative * damagemult * 150;
2573 victim->frameTarget = 0;
2574 victim->animTarget = staggerbackhardanim;
2575 victim->targetyaw = targetyaw + 180;
2577 victim->stunned = 1;
2580 victim->Puff(abdomen);
2581 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2588 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2589 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2593 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2594 if (tutoriallevel != 1) {
2595 emit_sound_at(thudsound, victim->coords);
2597 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2598 if (tutoriallevel != 1) {
2599 emit_sound_at(whooshhitsound, victim->coords);
2602 if (tutoriallevel != 1) {
2603 emit_sound_at(heavyimpactsound, victim->coords);
2607 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2610 relative = victim->coords - coords;
2612 Normalise(&relative);
2614 Normalise(&relative);
2615 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2616 victim->skeleton.joints[i].velocity = relative * 5;
2618 victim->jointVel(abdomen) += relative * damagemult * 400;
2620 victim->frameTarget = 0;
2621 victim->animTarget = staggerbackhardanim;
2622 victim->targetyaw = targetyaw + 180;
2624 victim->stunned = 1;
2626 victim->Puff(abdomen);
2627 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2633 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2634 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2635 if (victim->id == 0)
2637 emit_sound_at(landsound2, victim->coords);
2643 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2644 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2645 if (victim->id == 0)
2648 if (weaponactive != -1) {
2649 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2650 if (weapons[victim->weaponids[0]].getType() == staff)
2651 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2652 if (weapons[weaponids[0]].getType() == staff)
2653 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2655 emit_sound_at(swordstaffsound, victim->coords);
2657 emit_sound_at(metalhitsound, victim->coords);
2665 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2666 if (weaponactive != -1) {
2669 weapons[weaponids[0]].owner = -1;
2670 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);
2672 weapons[weaponids[0]].velocity = aim * 50;
2673 weapons[weaponids[0]].tipvelocity = aim * 50;
2674 weapons[weaponids[0]].missed = 0;
2675 weapons[weaponids[0]].hitsomething = 0;
2676 weapons[weaponids[0]].freetime = 0;
2677 weapons[weaponids[0]].firstfree = 1;
2678 weapons[weaponids[0]].physics = 0;
2681 weaponids[0] = weaponids[num_weapons];
2687 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2689 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2691 if (tutoriallevel != 1)
2692 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2694 award_bonus(id, Slicebonus);
2695 if (tutoriallevel != 1) {
2696 emit_sound_at(knifeslicesound, victim->coords);
2698 //victim->jointVel(abdomen)+=relative*damagemult*200;
2699 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2700 if (victim->id != 0 || difficulty == 2) {
2701 victim->frameTarget = 0;
2702 victim->animTarget = staggerbackhardanim;
2703 victim->targetyaw = targetyaw + 180;
2707 victim->lowreversaldelay = 0;
2708 victim->highreversaldelay = 0;
2709 if (aitype != playercontrolled)
2710 weaponmissdelay = .6;
2712 if (tutoriallevel != 1)
2713 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2714 weapons[weaponids[weaponactive]].bloody = 1;
2715 if (tutoriallevel != 1)
2716 weapons[weaponids[weaponactive]].blooddrip += 3;
2718 XYZ footvel, footpoint;
2720 if (skeleton.free) {
2721 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2723 if (!skeleton.free) {
2724 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2726 if (tutoriallevel != 1) {
2728 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2729 footvel = DoRotation(facing, 0, 90, 0) * .8;
2731 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2732 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2733 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2734 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2736 if (tutoriallevel == 1) {
2737 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2739 victim->DoDamage(damagemult * 0);
2742 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2743 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2744 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2745 award_bonus(id, Slashbonus);
2747 if (tutoriallevel != 1) {
2748 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2749 victim->DoBloodBig(2 / victim->armorhigh, 190);
2751 victim->DoBloodBig(2 / victim->armorhigh, 185);
2752 victim->deathbleeding = 1;
2753 emit_sound_at(swordslicesound, victim->coords);
2755 //victim->jointVel(abdomen)+=relative*damagemult*200;
2756 if (tutoriallevel != 1) {
2757 victim->frameTarget = 0;
2758 victim->animTarget = staggerbackhardanim;
2759 victim->targetyaw = targetyaw + 180;
2763 if (tutoriallevel != 1) {
2764 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2765 weapons[weaponids[weaponactive]].bloody = 1;
2766 weapons[weaponids[weaponactive]].blooddrip += 3;
2768 float bloodlossamount;
2769 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2770 victim->bloodloss += bloodlossamount / victim->armorhigh;
2771 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2772 victim->DoDamage(damagemult * 0);
2774 XYZ footvel, footpoint;
2776 if (skeleton.free) {
2777 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2779 if (!skeleton.free) {
2780 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2783 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2784 footvel = DoRotation(facing, 0, 90, 0) * .8;
2786 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2787 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2788 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2789 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2792 if (victim->weaponactive != -1) {
2793 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2794 if (weapons[victim->weaponids[0]].getType() == staff)
2795 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2796 if (weapons[weaponids[0]].getType() == staff)
2797 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2799 emit_sound_at(swordstaffsound, victim->coords);
2801 emit_sound_at(metalhitsound, victim->coords);
2807 victim->Puff(righthand);
2809 victim->frameTarget = 0;
2810 victim->animTarget = staggerbackhighanim;
2811 victim->targetyaw = targetyaw + 180;
2813 weapons[victim->weaponids[0]].owner = -1;
2814 aim = DoRotation(facing, 0, 90, 0) * 21;
2816 weapons[victim->weaponids[0]].velocity = aim * -.2;
2817 weapons[victim->weaponids[0]].tipvelocity = aim;
2818 weapons[victim->weaponids[0]].missed = 1;
2819 weapons[weaponids[0]].hitsomething = 0;
2820 weapons[victim->weaponids[0]].freetime = 0;
2821 weapons[victim->weaponids[0]].firstfree = 1;
2822 weapons[victim->weaponids[0]].physics = 1;
2823 victim->num_weapons--;
2824 if (victim->num_weapons) {
2825 victim->weaponids[0] = victim->weaponids[num_weapons];
2826 if (victim->weaponstuck == victim->num_weapons)
2827 victim->weaponstuck = 0;
2829 victim->weaponactive = -1;
2830 for (unsigned i = 0; i < Person::players.size(); i++) {
2831 Person::players[i]->wentforweapon = 0;
2838 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2839 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2840 if (tutoriallevel != 1) {
2841 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2845 if (Random() % 2 || creature == wolftype) {
2848 emit_sound_at(staffheadsound, victim->coords);
2852 relative = victim->coords - coords;
2854 Normalise(&relative);
2855 relative = DoRotation(relative, 0, 90, 0);
2857 Normalise(&relative);
2858 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2859 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2861 victim->jointVel(head) += relative * damagemult * 230;
2862 victim->jointVel(neck) += relative * damagemult * 230;
2865 if (tutoriallevel != 1) {
2866 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2868 award_bonus(id, solidhit, 30);
2873 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2874 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2875 if (tutoriallevel != 1) {
2876 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2880 if (Random() % 2 || creature == wolftype) {
2883 emit_sound_at(staffheadsound, victim->coords);
2887 relative = victim->coords - coords;
2889 Normalise(&relative);
2890 relative = DoRotation(relative, 0, -90, 0);
2891 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2892 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2894 victim->jointVel(head) += relative * damagemult * 220;
2895 victim->jointVel(neck) += relative * damagemult * 220;
2898 if (tutoriallevel != 1) {
2899 victim->DoDamage(damagemult * 350 / victim->protectionhead);
2901 award_bonus(id, solidhit, 60);
2906 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
2907 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
2909 if (tutoriallevel != 1) {
2911 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
2914 if (Random() % 2 || creature == wolftype) {
2917 emit_sound_at(staffbodysound, victim->coords);
2919 victim->skeleton.longdead = 0;
2920 victim->skeleton.free = 1;
2921 victim->skeleton.broken = 0;
2923 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2924 victim->skeleton.joints[i].velchange = 0;
2925 victim->skeleton.joints[i].locked = 0;
2926 //victim->skeleton.joints[i].velocity=0;
2932 /*relative=victim->coords-coords;
2934 Normalise(&relative);
2935 relative=DoRotation(relative,0,90,0);*/
2937 Normalise(&relative);
2938 if (!victim->dead) {
2939 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2940 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
2943 victim->jointVel(abdomen) += relative * damagemult * 40;
2946 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2947 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
2950 //victim->jointVel(abdomen)+=relative*damagemult*20;
2952 victim->Puff(abdomen);
2953 if (tutoriallevel != 1) {
2954 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
2956 if (!victim->dead) {
2957 award_bonus(id, solidhit, 40);
2963 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
2964 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
2969 relative = victim->coords - coords;
2971 Normalise(&relative);
2975 if (animation[victim->animTarget].height == lowheight) {
2981 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2982 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2984 victim->jointVel(head) += relative * damagemult * 200;
2985 if (tutoriallevel != 1) {
2986 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2989 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2990 if (victim->howactive == typesleeping)
2991 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2992 if (creature == wolftype) {
2993 emit_sound_at(clawslicesound, victim->coords, 128.);
2995 victim->DoBloodBig(2 / victim->armorhead, 175);
2998 if (victim->damage >= victim->damagetolerance)
3000 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3001 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3003 victim->jointVel(abdomen) += relative * damagemult * 200;
3004 victim->frameTarget = 0;
3005 victim->animTarget = staggerbackhighanim;
3006 victim->targetyaw = targetyaw + 180;
3008 if (tutoriallevel != 1) {
3009 emit_sound_at(landsound2, victim->coords, 128.);
3011 victim->Puff(abdomen);
3012 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3013 if (creature == wolftype) {
3014 emit_sound_at(clawslicesound, victim->coords, 128.);
3016 victim->DoBloodBig(2 / victim->armorhigh, 170);
3023 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3024 if ((victim->animTarget != jumpupanim) &&
3025 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3026 (victim != this->shared_from_this())) {
3030 if (tutoriallevel != 1) {
3031 emit_sound_at(landsound2, victim->coords, 128.);
3034 relative = victim->coords - coords;
3036 Normalise(&relative);
3038 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3041 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3042 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3044 relative = DoRotation(relative, 0, -90, 0);
3046 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3047 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)
3048 victim->skeleton.joints[i].velocity = relative * 80;
3050 victim->Puff(rightankle);
3051 victim->Puff(leftankle);
3052 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3054 if (victim->damage >= victim->damagetolerance)
3056 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3057 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3059 relative = DoRotation(relative, 0, -90, 0);
3060 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3061 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)
3062 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3064 victim->jointVel(abdomen) += relative * damagemult * 200;
3065 victim->frameTarget = 0;
3066 victim->animTarget = staggerbackhighanim;
3067 victim->targetyaw = targetyaw + 180;
3069 if (tutoriallevel != 1) {
3070 emit_sound_at(landsound2, victim->coords, 128.);
3072 victim->Puff(abdomen);
3073 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3081 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3082 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3090 if (tutoriallevel != 1) {
3091 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3093 if (creature == wolftype) {
3094 emit_sound_at(clawslicesound, victim->coords, 128);
3096 victim->DoBloodBig(2 / victim->armorhigh, 170);
3100 relative = victim->coords - oldcoords;
3102 Normalise(&relative);
3103 //relative=DoRotation(relative,0,-90,0);
3104 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3105 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3107 victim->jointVel(abdomen) += relative * damagemult * 200;
3109 victim->Puff(abdomen);
3110 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3112 award_bonus(id, Reversal);
3115 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3116 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3117 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3118 weapons[victim->weaponids[victim->weaponactive]].owner = id;
3120 if (num_weapons > 0) {
3121 weaponids[num_weapons] = weaponids[victim->weaponactive];
3124 weaponids[0] = victim->weaponids[victim->weaponactive];
3125 victim->num_weapons--;
3126 if (victim->num_weapons > 0) {
3127 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3129 victim->weaponactive = -1;
3134 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3142 emit_sound_at(whooshhitsound, victim->coords, 128.);
3145 relative = victim->coords - oldcoords;
3147 Normalise(&relative);
3148 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3149 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3151 victim->jointVel(abdomen) += relative * damagemult * 200;
3153 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3156 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3165 award_bonus(id, staffreversebonus);
3167 if (tutoriallevel != 1) {
3168 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3171 award_bonus(id, staffreversebonus); // Huh, again?
3174 relative = victim->coords - oldcoords;
3176 Normalise(&relative);
3177 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3178 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3180 victim->jointVel(abdomen) += relative * damagemult * 200;
3182 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3185 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3191 Normalise(&relative);
3193 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3194 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3196 victim->jointVel(lefthand) *= .1;
3197 victim->jointVel(leftwrist) *= .2;
3198 victim->jointVel(leftelbow) *= .5;
3199 victim->jointVel(leftshoulder) *= .7;
3200 victim->jointVel(righthand) *= .1;
3201 victim->jointVel(rightwrist) *= .2;
3202 victim->jointVel(rightelbow) *= .5;
3203 victim->jointVel(rightshoulder) *= .7;
3205 victim->Puff(abdomen);
3206 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3208 award_bonus(id, Reversal);
3212 if (weaponactive != -1 || creature == wolftype)
3214 if (creature == rabbittype && weaponactive != -1)
3215 if (weapons[weaponids[0]].getType() == staff)
3218 if (weaponactive != -1) {
3219 victim->DoBloodBig(2 / victim->armorhigh, 225);
3220 emit_sound_at(knifeslicesound, victim->coords);
3221 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3222 weapons[weaponids[weaponactive]].bloody = 1;
3223 weapons[weaponids[weaponactive]].blooddrip += 3;
3225 if (weaponactive == -1 && creature == wolftype) {
3227 emit_sound_at(clawslicesound, victim->coords, 128.);
3229 victim->DoBloodBig(2 / victim->armorhigh, 175);
3236 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3242 Normalise(&relative);
3244 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3245 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3247 victim->jointVel(lefthand) *= .1 - 1;
3248 victim->jointVel(leftwrist) *= .2 - 1;
3249 victim->jointVel(leftelbow) *= .5 - 1;
3250 victim->jointVel(leftshoulder) *= .7 - 1;
3251 victim->jointVel(righthand) *= .1 - 1;
3252 victim->jointVel(rightwrist) *= .2 - 1;
3253 victim->jointVel(rightelbow) *= .5 - 1;
3254 victim->jointVel(rightshoulder) *= .7 - 1;
3256 award_bonus(id, swordreversebonus);
3259 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3267 if (tutoriallevel != 1) {
3268 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3272 relative = victim->coords - oldcoords;
3274 Normalise(&relative);
3275 relative = DoRotation(relative, 0, -90, 0);
3276 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3277 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3279 victim->jointVel(abdomen) += relative * damagemult * 200;
3280 victim->Puff(abdomen);
3281 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3283 award_bonus(id, Reversal);
3286 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3289 victim->skeleton.spinny = 0;
3291 relative = facing * -1;
3293 Normalise(&relative);
3294 if (victim->id == 0)
3296 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3297 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3299 victim->damage = victim->damagetolerance;
3300 victim->permanentdamage = victim->damagetolerance - 1;
3303 if (weaponactive != -1 || creature == wolftype)
3305 if (creature == rabbittype && weaponactive != -1)
3306 if (weapons[weaponids[0]].getType() == staff)
3309 if (weaponactive != -1) {
3310 victim->DoBloodBig(200, 225);
3311 emit_sound_at(knifeslicesound, victim->coords);
3313 weapons[weaponids[weaponactive]].bloody = 2;
3314 weapons[weaponids[weaponactive]].blooddrip += 5;
3317 if (creature == wolftype && weaponactive == -1) {
3318 emit_sound_at(clawslicesound, victim->coords, 128.);
3320 victim->DoBloodBig(2, 175);
3323 award_bonus(id, spinecrusher);
3326 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3327 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3329 if (animTarget == knifefollowanim)
3330 victim->DoBloodBig(200, 210);
3331 if (animTarget == knifesneakattackanim) {
3332 XYZ footvel, footpoint;
3334 footpoint = weapons[weaponids[0]].tippoint;
3336 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3337 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3338 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3339 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3340 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3341 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3342 victim->DoBloodBig(200, 195);
3343 award_bonus(id, tracheotomy);
3345 if (animTarget == knifefollowanim) {
3346 award_bonus(id, Stabbonus);
3347 XYZ footvel, footpoint;
3349 footpoint = weapons[weaponids[0]].tippoint;
3351 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3352 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3353 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3354 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3355 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3356 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3359 victim->bloodloss += 10000;
3360 victim->velocity = 0;
3361 emit_sound_at(fleshstabsound, victim->coords);
3363 weapons[weaponids[weaponactive]].bloody = 2;
3364 weapons[weaponids[weaponactive]].blooddrip += 5;
3368 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3370 victim->velocity = 0;
3371 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3372 victim->skeleton.joints[i].velocity = 0;
3374 if (animTarget == knifefollowanim) {
3376 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3377 victim->skeleton.joints[i].velocity = 0;
3380 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3381 emit_sound_at(fleshstabremovesound, victim->coords);
3383 weapons[weaponids[weaponactive]].bloody = 2;
3384 weapons[weaponids[weaponactive]].blooddrip += 5;
3386 XYZ footvel, footpoint;
3388 footpoint = weapons[weaponids[0]].tippoint;
3390 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3391 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3392 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3393 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3394 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3395 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3399 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3400 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3401 award_bonus(id, backstab);
3405 XYZ footvel, footpoint;
3407 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3409 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3410 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3411 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3412 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3413 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3414 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3415 victim->DoBloodBig(200, 180);
3416 victim->DoBloodBig(200, 215);
3417 victim->bloodloss += 10000;
3418 victim->velocity = 0;
3419 emit_sound_at(fleshstabsound, victim->coords);
3421 weapons[weaponids[weaponactive]].bloody = 2;
3422 weapons[weaponids[weaponactive]].blooddrip += 5;
3426 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3428 victim->velocity = 0;
3429 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3430 victim->skeleton.joints[i].velocity = 0;
3432 if (weaponactive != -1) {
3433 emit_sound_at(fleshstabremovesound, victim->coords);
3435 weapons[weaponids[weaponactive]].bloody = 2;
3436 weapons[weaponids[weaponactive]].blooddrip += 5;
3438 XYZ footvel, footpoint;
3440 footpoint = weapons[weaponids[0]].tippoint;
3442 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3443 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3444 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3445 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3446 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3447 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3451 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3459 if (weaponactive == -1) {
3460 if (tutoriallevel != 1) {
3461 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3466 if (weaponactive != -1 || creature == wolftype)
3468 if (creature == rabbittype && weaponactive != -1)
3469 if (weapons[weaponids[0]].getType() == staff)
3472 if (weaponactive != -1) {
3473 victim->DoBloodBig(2 / victim->armorhead, 225);
3474 emit_sound_at(knifeslicesound, victim->coords);
3475 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3476 weapons[weaponids[weaponactive]].bloody = 1;
3477 weapons[weaponids[weaponactive]].blooddrip += 3;
3479 if (weaponactive == -1 && creature == wolftype) {
3480 emit_sound_at(clawslicesound, victim->coords, 128.);
3482 victim->DoBloodBig(2 / victim->armorhead, 175);
3486 award_bonus(id, Reversal);
3491 relative = facing * -1;
3493 Normalise(&relative);
3494 relative = DoRotation(relative, 0, 90, 0);
3496 Normalise(&relative);
3497 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3498 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3500 victim->jointVel(head) += relative * damagemult * 200;
3501 if (victim->damage < victim->damagetolerance - 100)
3502 victim->velocity = relative * 200;
3503 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3504 victim->velocity = 0;
3507 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3511 relative = facing * -1;
3513 Normalise(&relative);
3514 relative = DoRotation(relative, 0, 90, 0);
3516 Normalise(&relative);
3517 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3518 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3520 victim->jointVel(head) += relative * damagemult * 200;
3523 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3524 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3525 award_bonus(id, reverseko);
3531 if (frameTarget > animation[animCurrent].numframes - 1) {
3534 animTarget = getIdle();
3538 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3539 animTarget = rollanim;
3541 emit_sound_at(movewhooshsound, coords, 128.);
3543 if (animCurrent == staggerbackhighanim) {
3544 animTarget = getIdle();
3546 if (animCurrent == staggerbackhardanim) {
3547 animTarget = getIdle();
3549 if (animCurrent == removeknifeanim) {
3550 animTarget = getIdle();
3552 if (animCurrent == crouchremoveknifeanim) {
3553 animTarget = getCrouch();
3555 if (animCurrent == backhandspringanim) {
3556 animTarget = getIdle();
3558 if (animCurrent == dodgebackanim) {
3559 animTarget = getIdle();
3561 if (animCurrent == drawleftanim) {
3562 animTarget = getIdle();
3564 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3565 animTarget = getIdle();
3566 if (animCurrent == crouchdrawrightanim) {
3567 animTarget = getCrouch();
3569 if (weaponactive == -1)
3571 else if (weaponactive == 0) {
3573 if (num_weapons == 2) {
3575 buffer = weaponids[0];
3576 weaponids[0] = weaponids[1];
3577 weaponids[1] = buffer;
3581 if (weaponactive == -1) {
3582 emit_sound_at(knifesheathesound, coords, 128.);
3584 if (weaponactive != -1) {
3585 emit_sound_at(knifedrawsound, coords, 128.);
3588 if (animCurrent == rollanim) {
3589 animTarget = getCrouch();
3594 if (animTarget == walljumprightkickanim) {
3597 if (animTarget == walljumpleftkickanim) {
3600 animTarget = jumpdownanim;
3602 if (animCurrent == climbanim) {
3603 animTarget = getCrouch();
3605 coords += facing * .1;
3606 if (!isnormal(coords.x))
3617 if (animTarget == rabbitkickreversalanim) {
3618 animTarget = getCrouch();
3621 if (animTarget == jumpreversalanim) {
3622 animTarget = getCrouch();
3625 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3626 if (attackkeydown && animTarget != walljumpfrontanim) {
3628 float closestdist = -1;
3630 if (Person::players.size() > 1)
3631 for (unsigned i = 0; i < Person::players.size(); i++) {
3632 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3633 distance = distsq(&Person::players[i]->coords, &coords);
3634 if (closestdist == -1 || distance < closestdist) {
3635 closestdist = distance;
3640 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3641 victim = Person::players[closest];
3642 animTarget = walljumprightkickanim;
3644 XYZ rotatetarget = victim->coords - coords;
3645 Normalise(&rotatetarget);
3646 yaw = -asin(0 - rotatetarget.x);
3648 if (rotatetarget.z < 0)
3650 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3651 velocity = (victim->coords - coords) * 4;
3656 if (animTarget == walljumpbackanim) {
3657 animTarget = backflipanim;
3659 velocity = facing * -8;
3662 resume_stream(whooshsound);
3664 if (animTarget == walljumprightanim) {
3665 animTarget = rightflipanim;
3669 velocity = DoRotation(facing, 0, 30, 0) * -8;
3672 if (animTarget == walljumpfrontanim) {
3673 animTarget = frontflipanim;
3677 velocity = facing * 8;
3681 resume_stream(whooshsound);
3683 if (animTarget == walljumpleftanim) {
3684 if (attackkeydown) {
3686 float closestdist = -1;
3688 if (Person::players.size() > 1)
3689 for (unsigned i = 0; i < Person::players.size(); i++) {
3690 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3691 distance = distsq(&Person::players[i]->coords, &coords);
3692 if (closestdist == -1 || distance < closestdist) {
3693 closestdist = distance;
3698 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3699 victim = Person::players[closest];
3700 animTarget = walljumpleftkickanim;
3702 XYZ rotatetarget = victim->coords - coords;
3703 Normalise(&rotatetarget);
3704 yaw = -asin(0 - rotatetarget.x);
3706 if (rotatetarget.z < 0)
3708 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3709 velocity = (victim->coords - coords) * 4;
3714 if (animTarget != walljumpleftkickanim) {
3715 animTarget = leftflipanim;
3719 velocity = DoRotation(facing, 0, -30, 0) * -8;
3723 resume_stream(whooshsound);
3725 if (animTarget == sneakattackanim) {
3726 animCurrent = getCrouch();
3727 animTarget = getCrouch();
3734 transspeed = 1000000;
3735 targetheadyaw += 180;
3736 coords -= facing * .7;
3738 coords.y = terrain.getHeight(coords.x, coords.z);
3742 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3743 animTarget = getIdle();
3746 coords.y = terrain.getHeight(coords.x, coords.z);
3750 if (animCurrent == knifefollowanim) {
3751 animTarget = getIdle();
3754 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3755 float ycoords = oldcoords.y;
3756 animTarget = getStop();
3761 transspeed = 1000000;
3762 targetheadyaw += 180;
3763 if (!isnormal(coords.x))
3765 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3766 oldcoords = coords + facing * .5;
3767 else if (animCurrent == sweepreversalanim)
3768 oldcoords = coords + facing * 1.1;
3769 else if (animCurrent == upunchreversalanim) {
3770 oldcoords = coords + facing * 1.5;
3773 targetheadyaw += 180;
3776 } else if (animCurrent == knifeslashreversalanim) {
3777 oldcoords = coords + facing * .5;
3780 targetheadyaw += 90;
3783 } else if (animCurrent == staffspinhitreversalanim) {
3786 targetheadyaw += 180;
3791 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3793 oldcoords.y = ycoords;
3794 currentoffset = coords - oldcoords;
3800 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3805 if (animation[animTarget].attack == reversed) {
3807 if (animTarget == sweepreversedanim)
3809 animTarget = backhandspringanim;
3811 emit_sound_at(landsound, coords, 128);
3813 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3814 animTarget = rollanim;
3817 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3818 coords.y = oldcoords.y;
3820 if (animCurrent == knifeslashreversedanim) {
3821 animTarget = rollanim;
3826 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3827 coords.y = oldcoords.y;
3831 animTarget = jumpdownanim;
3834 animTarget = getIdle();
3836 animTarget = getIdle();
3837 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3838 animTarget = getIdle();
3840 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3841 coords.y = oldcoords.y;
3842 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3843 targetoffset.y = coords.y;
3845 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3846 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3847 currentoffset.y -= (coords.y - targetoffset.y);
3848 coords.y = targetoffset.y;
3850 normalsupdatedelay = 0;
3852 if (animCurrent == upunchanim) {
3853 animTarget = getStop();
3854 normalsupdatedelay = 0;
3857 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3861 if (num_weapons > 0)
3862 if (weapons[0].getType() == staff)
3868 rabbitkickragdoll = 1;
3870 if (animCurrent == rabbitkickreversedanim) {
3876 skeleton.spinny = 0;
3877 SolidHitBonus(!id); // FIXME: tricky id
3881 animTarget = rollanim;
3884 pause_sound(whooshsound);
3888 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3892 skeleton.spinny = 0;
3894 if (animCurrent == jumpreversedanim) {
3900 skeleton.spinny = 0;
3901 SolidHitBonus(!id); // FIXME: tricky id
3905 animTarget = rollanim;
3906 coords += facing * 2;
3908 pause_sound(whooshsound);
3913 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) {
3914 animTarget = getupfromfrontanim;
3916 } else if (animation[animCurrent].attack == normalattack) {
3917 animTarget = getIdle();
3920 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
3921 animTarget = blockhighleftstrikeanim;
3923 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
3924 animTarget = getIdle();
3927 if (animCurrent == spinkickanim && victim->skeleton.free) {
3928 if (creature == rabbittype)
3929 animTarget = fightidleanim;
3934 if (isIdle() && !wasIdle())
3935 normalsupdatedelay = 0;
3937 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
3938 animTarget = jumpdownanim;
3941 if (!skeleton.free) {
3943 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
3944 if (!isRun() || !wasRun()) {
3945 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3946 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
3947 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3948 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
3950 if (isRun() && wasRun()) {
3952 tempspeed = velspeed;
3953 if (tempspeed < 10 * speedmult)
3954 tempspeed = 10 * speedmult;
3955 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
3957 } else if (transspeed)
3958 target += multiplier * transspeed * speed * 2;
3960 if (!isRun() || !wasRun()) {
3961 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3962 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
3963 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3964 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
3968 if (animCurrent != animTarget)
3969 target = (target + oldtarget) / 2;
3972 frameCurrent = frameTarget;
3976 rot = targetrot * target;
3977 yaw += rot - oldrot;
3983 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
3985 for (int i = 0; i < skeleton.num_joints; i++) {
3986 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
3989 skeleton.FindForwards();
3991 for (int i = 0; i < skeleton.num_muscles; i++) {
3992 if (skeleton.muscles[i].visible) {
3993 skeleton.FindRotationMuscle(i, animTarget);
3996 for (int i = 0; i < skeleton.num_muscles; i++) {
3997 if (skeleton.muscles[i].visible) {
3998 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3999 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4000 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4001 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4002 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4003 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4008 for (int i = 0; i < skeleton.num_joints; i++) {
4009 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4012 skeleton.FindForwards();
4014 for (int i = 0; i < skeleton.num_muscles; i++) {
4015 if (skeleton.muscles[i].visible) {
4016 skeleton.FindRotationMuscle(i, animTarget);
4019 for (int i = 0; i < skeleton.num_muscles; i++) {
4020 if (skeleton.muscles[i].visible) {
4021 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4022 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4023 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4024 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4025 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4026 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4027 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4028 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4029 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4030 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4031 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4032 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4036 if (frameCurrent >= animation[animCurrent].numframes)
4037 frameCurrent = animation[animCurrent].numframes - 1;
4039 oldanimCurrent = animCurrent;
4040 oldanimTarget = animTarget;
4041 oldframeTarget = frameTarget;
4042 oldframeCurrent = frameCurrent;
4044 for (int i = 0; i < skeleton.num_joints; i++) {
4045 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4046 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4048 offset = currentoffset * (1 - target) + targetoffset * target;
4049 for (int i = 0; i < skeleton.num_muscles; i++) {
4050 if (skeleton.muscles[i].visible) {
4051 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4052 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4053 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4058 if (isLanding() && landhard) {
4061 animTarget = getLandhard();
4074 void Person::DoStuff()
4076 static XYZ terrainnormal;
4077 static XYZ flatfacing;
4078 static XYZ flatvelocity;
4079 static float flatvelspeed;
4083 static int bloodsize;
4084 static int startx, starty, endx, endy;
4085 static GLubyte color;
4086 static XYZ bloodvel;
4088 onfiredelay -= multiplier;
4089 if (onfiredelay < 0 && onfire) {
4090 if (Random() % 2 == 0) {
4096 crouchkeydowntime += multiplier;
4098 crouchkeydowntime = 0;
4099 jumpkeydowntime += multiplier;
4100 if (!jumpkeydown && skeleton.free)
4101 jumpkeydowntime = 0;
4103 if (hostile || damage > 0 || bloodloss > 0)
4106 if (isIdle() || isRun())
4109 if (num_weapons == 1 && weaponactive != -1)
4113 blooddimamount -= multiplier * .3;
4114 speechdelay -= multiplier;
4115 texupdatedelay -= multiplier;
4116 interestdelay -= multiplier;
4117 flamedelay -= multiplier;
4118 parriedrecently -= multiplier;
4120 victim = this->shared_from_this();
4125 speed = 1.1 * speedmult;
4127 speed = 1.0 * speedmult;
4129 rabbitkickragdoll = 0;
4133 if (id != 0 && (creature == rabbittype || difficulty != 2))
4135 if (id != 0 && creature == wolftype && difficulty == 2) {
4137 if (aitype != passivetype) {
4139 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) {
4145 if (animTarget == wolfrunninganim && !superruntoggle) {
4146 animTarget = getRun();
4150 if (weaponactive == -1 && num_weapons > 0) {
4151 if (weapons[weaponids[0]].getType() == staff) {
4157 burnt += multiplier;
4161 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4163 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4169 vel[0] = velocity.x;
4170 vel[1] = velocity.y;
4171 vel[2] = velocity.z;
4174 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4175 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4179 while (flamedelay < 0 && onfire) {
4181 howmany = abs(Random() % (skeleton.num_joints));
4183 flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4185 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4187 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4189 flatfacing = skeleton.joints[howmany].position * scale + coords;
4190 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4193 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4195 howmany = abs(Random() % (skeleton.num_joints));
4197 flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4199 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4201 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4203 flatfacing = skeleton.joints[howmany].position * scale + coords;
4204 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4208 bleeding -= multiplier * .3;
4209 if (bloodtoggle == 2) {
4210 skeleton.drawmodel.textureptr.bind();
4211 if (bleeding <= 0 && (detail != 2 || osx))
4216 if (neckspurtamount > 0) {
4217 neckspurtamount -= multiplier;
4218 neckspurtdelay -= multiplier * 3;
4219 neckspurtparticledelay -= multiplier * 3;
4220 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4223 if (!skeleton.free) {
4224 bloodvel.z = 5 * neckspurtamount;
4225 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4227 if (skeleton.free) {
4228 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4231 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4233 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4235 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4237 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4238 neckspurtparticledelay = .05;
4240 if (neckspurtdelay < 0) {
4245 if (deathbleeding > 0 && dead != 2) {
4246 if (deathbleeding < 5)
4247 bleeddelay -= deathbleeding * multiplier / 4;
4249 bleeddelay -= 5 * multiplier / 4;
4250 if (bleeddelay < 0 && bloodtoggle) {
4256 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4258 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4260 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4262 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4265 bloodloss += deathbleeding * multiplier * 80;
4266 deathbleeding -= multiplier * 1.6;
4267 if (deathbleeding < 0)
4269 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4270 if (weaponactive != -1) {
4271 weapons[weaponids[0]].owner = -1;
4272 weapons[weaponids[0]].velocity = velocity * scale * -.3;
4273 weapons[weaponids[0]].velocity.x += .01;
4274 weapons[weaponids[0]].tipvelocity = velocity * scale;
4275 weapons[weaponids[0]].missed = 1;
4276 weapons[weaponids[0]].hitsomething = 0;
4277 weapons[weaponids[0]].freetime = 0;
4278 weapons[weaponids[0]].firstfree = 1;
4279 weapons[weaponids[0]].physics = 1;
4282 weaponids[0] = weaponids[num_weapons];
4283 if (weaponstuck == num_weapons)
4287 for (unsigned i = 0; i < Person::players.size(); i++) {
4288 Person::players[i]->wentforweapon = 0;
4300 if (!dead && creature == wolftype) {
4301 award_bonus(0, Wolfbonus);
4304 if (animTarget == knifefollowedanim && !skeleton.free) {
4305 for (int i = 0; i < skeleton.num_joints; i++) {
4306 skeleton.joints[i].velocity = 0;
4307 skeleton.joints[i].velocity.y = -2;
4310 if (id != 0 && unconscioustime > .1) {
4318 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4319 texupdatedelay = .12;
4321 bloodsize = 5 - realtexdetail;
4325 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4326 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4327 endx = startx + bloodsize;
4328 endy = starty + bloodsize;
4338 if (endx > skeleton.skinsize - 1) {
4339 endx = skeleton.skinsize - 1;
4342 if (endy > skeleton.skinsize - 1) {
4343 endy = skeleton.skinsize - 1;
4351 for (i = startx; i < endx; i++) {
4352 for (j = starty; j < endy; j++) {
4353 if (Random() % 2 == 0) {
4354 color = Random() % 85 + 170;
4355 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4356 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4357 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4358 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4362 if (!osx && detail > 1) {
4363 skeleton.drawmodel.textureptr.bind();
4367 if (!skeleton.free) {
4368 bleedy -= 4 / realtexdetail;
4370 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4372 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4374 if (skeleton.free) {
4375 bleedx += 4 * direction / realtexdetail;
4377 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4379 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4383 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4384 righthandmorphness = targetrighthandmorphness;
4385 righthandmorphstart = righthandmorphend;
4386 } else if (righthandmorphness > targetrighthandmorphness) {
4387 righthandmorphness -= multiplier * 4;
4388 } else if (righthandmorphness < targetrighthandmorphness) {
4389 righthandmorphness += multiplier * 4;
4392 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4393 lefthandmorphness = targetlefthandmorphness;
4394 lefthandmorphstart = lefthandmorphend;
4395 } else if (lefthandmorphness > targetlefthandmorphness) {
4396 lefthandmorphness -= multiplier * 4;
4397 } else if (lefthandmorphness < targetlefthandmorphness) {
4398 lefthandmorphness += multiplier * 4;
4401 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4402 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4403 tailmorphness = targettailmorphness;
4404 tailmorphstart = tailmorphend;
4405 } else if (tailmorphness > targettailmorphness) {
4406 tailmorphness -= multiplier * 10;
4407 } else if (tailmorphness < targettailmorphness) {
4408 tailmorphness += multiplier * 10;
4412 if (creature == wolftype) {
4413 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4414 tailmorphness = targettailmorphness;
4415 tailmorphstart = tailmorphend;
4416 } else if (tailmorphness > targettailmorphness) {
4417 tailmorphness -= multiplier * 2;
4418 } else if (tailmorphness < targettailmorphness) {
4419 tailmorphness += multiplier * 2;
4423 if (headmorphend == 3 || headmorphstart == 3) {
4424 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4425 headmorphness = targetheadmorphness;
4426 headmorphstart = headmorphend;
4427 } else if (headmorphness > targetheadmorphness) {
4428 headmorphness -= multiplier * 7;
4429 } else if (headmorphness < targetheadmorphness) {
4430 headmorphness += multiplier * 7;
4432 } else if (headmorphend == 5 || headmorphstart == 5) {
4433 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4434 headmorphness = targetheadmorphness;
4435 headmorphstart = headmorphend;
4436 } else if (headmorphness > targetheadmorphness) {
4437 headmorphness -= multiplier * 10;
4438 } else if (headmorphness < targetheadmorphness) {
4439 headmorphness += multiplier * 10;
4442 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4443 headmorphness = targetheadmorphness;
4444 headmorphstart = headmorphend;
4445 } else if (headmorphness > targetheadmorphness) {
4446 headmorphness -= multiplier * 4;
4447 } else if (headmorphness < targetheadmorphness) {
4448 headmorphness += multiplier * 4;
4452 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4453 chestmorphness = targetchestmorphness;
4454 chestmorphstart = chestmorphend;
4455 } else if (chestmorphness > targetchestmorphness) {
4456 chestmorphness -= multiplier;
4457 } else if (chestmorphness < targetchestmorphness) {
4458 chestmorphness += multiplier;
4461 if (dead != 2 && howactive <= typesleeping) {
4462 if (chestmorphstart == 0 && chestmorphend == 0) {
4464 targetchestmorphness = 1;
4467 if (chestmorphstart != 0 && chestmorphend != 0) {
4469 targetchestmorphness = 1;
4471 if (environment == snowyenvironment) {
4475 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4477 footvel = skeleton.specialforward[0] * -1;
4479 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4481 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4482 if (animTarget == sleepanim)
4483 footvel = DoRotation(footvel, 0, 90, 0);
4484 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4488 if (!dead && howactive < typesleeping) {
4489 blinkdelay -= multiplier * 2;
4490 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4492 targetheadmorphness = 1;
4494 blinkdelay = (float)(abs(Random() % 40)) / 5;
4496 if (headmorphstart == 3 && headmorphend == 3) {
4498 targetheadmorphness = 1;
4503 twitchdelay -= multiplier * 1.5;
4504 if (animTarget != hurtidleanim) {
4505 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4507 targetheadmorphness = 1;
4509 twitchdelay = (float)(abs(Random() % 40)) / 5;
4511 if (headmorphstart == 5 && headmorphend == 5) {
4513 targetheadmorphness = 1;
4517 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4518 twitchdelay3 -= multiplier * 1;
4519 if (Random() % 2 == 0) {
4520 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4521 righthandmorphness = 0;
4522 targetrighthandmorphness = 1;
4523 righthandmorphend = 1;
4524 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4526 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4527 righthandmorphness = 0;
4528 targetrighthandmorphness = 1;
4529 righthandmorphend = 0;
4532 if (Random() % 2 == 0) {
4533 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4534 lefthandmorphness = 0;
4535 targetlefthandmorphness = 1;
4536 lefthandmorphend = 1;
4537 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4539 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4540 lefthandmorphness = 0;
4541 targetlefthandmorphness = 1;
4542 lefthandmorphend = 0;
4548 if (creature == rabbittype) {
4549 if (howactive < typesleeping)
4550 twitchdelay2 -= multiplier * 1.5;
4552 twitchdelay2 -= multiplier * 0.5;
4553 if (howactive <= typesleeping) {
4554 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4556 targettailmorphness = 1;
4558 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4560 if (tailmorphstart == 1 && tailmorphend == 1) {
4562 targettailmorphness = 1;
4565 if (tailmorphstart == 2 && tailmorphend == 2) {
4567 targettailmorphness = 1;
4574 if (creature == wolftype) {
4575 twitchdelay2 -= multiplier * 1.5;
4576 if (tailmorphend != 0)
4577 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4579 targettailmorphness = 1;
4583 if (tailmorphend != 5)
4584 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4586 targettailmorphness = 1;
4590 if (twitchdelay2 <= 0) {
4591 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4593 targettailmorphness = 1;
4596 if (tailmorphstart == 1 && tailmorphend == 1) {
4598 targettailmorphness = 1;
4601 if (tailmorphstart == 2 && tailmorphend == 2) {
4603 targettailmorphness = 1;
4606 if (tailmorphstart == 3 && tailmorphend == 3) {
4608 targettailmorphness = 1;
4611 if (tailmorphstart == 4 && tailmorphend == 4) {
4613 targettailmorphness = 1;
4620 unconscioustime = 0;
4622 if (dead == 1 || howactive == typesleeping) {
4623 unconscioustime += multiplier;
4624 //If unconscious, close eyes and mouth
4625 if (righthandmorphend != 0)
4626 righthandmorphness = 0;
4627 righthandmorphend = 0;
4628 targetrighthandmorphness = 1;
4630 if (lefthandmorphend != 0)
4631 lefthandmorphness = 0;
4632 lefthandmorphend = 0;
4633 targetlefthandmorphness = 1;
4635 if (headmorphend != 3 && headmorphend != 5)
4638 targetheadmorphness = 1;
4642 if (howactive > typesleeping) {
4645 if (bloodtoggle && !bled) {
4646 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4648 if (bloodtoggle && !bled)
4649 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4650 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4651 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4655 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4660 if (dead == 2 || howactive > typesleeping) {
4661 //If dead, open mouth and hands
4662 if (righthandmorphend != 0)
4663 righthandmorphness = 0;
4664 righthandmorphend = 0;
4665 targetrighthandmorphness = 1;
4667 if (lefthandmorphend != 0)
4668 lefthandmorphness = 0;
4669 lefthandmorphend = 0;
4670 targetlefthandmorphness = 1;
4672 if (headmorphend != 2)
4675 targetheadmorphness = 1;
4678 if (stunned > 0 && !dead && headmorphend != 2) {
4679 if (headmorphend != 4)
4682 targetheadmorphness = 1;
4685 if (damage > damagetolerance && !dead) {
4688 unconscioustime = 0;
4690 if (creature == wolftype) {
4691 award_bonus(0, Wolfbonus);
4696 if (weaponactive != -1) {
4697 weapons[weaponids[0]].owner = -1;
4698 weapons[weaponids[0]].velocity = velocity * scale * -.3;
4699 weapons[weaponids[0]].velocity.x += .01;
4700 weapons[weaponids[0]].tipvelocity = velocity * scale;
4701 weapons[weaponids[0]].missed = 1;
4702 weapons[weaponids[0]].hitsomething = 0;
4703 weapons[weaponids[0]].freetime = 0;
4704 weapons[weaponids[0]].firstfree = 1;
4705 weapons[weaponids[0]].physics = 1;
4708 weaponids[0] = weaponids[num_weapons];
4709 if (weaponstuck == num_weapons)
4713 for (unsigned i = 0; i < Person::players.size(); i++) {
4714 Person::players[i]->wentforweapon = 0;
4720 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4729 damage -= multiplier * 13;
4731 permanentdamage -= multiplier * 4;
4732 if (isIdle() || isCrouch()) {
4734 permanentdamage -= multiplier * 4;
4738 if (permanentdamage < 0)
4739 permanentdamage = 0;
4740 if (superpermanentdamage < 0)
4741 superpermanentdamage = 0;
4742 if (permanentdamage < superpermanentdamage) {
4743 permanentdamage = superpermanentdamage;
4745 if (damage < permanentdamage) {
4746 damage = permanentdamage;
4748 if (dead == 1 && damage < damagetolerance) {
4752 for (int i = 0; i < skeleton.num_joints; i++) {
4753 skeleton.joints[i].velocity = 0;
4756 if (permanentdamage > damagetolerance && dead != 2) {
4759 if (weaponactive != -1) {
4760 weapons[weaponids[0]].owner = -1;
4761 weapons[weaponids[0]].velocity = velocity * scale * -.3;
4762 weapons[weaponids[0]].velocity.x += .01;
4763 weapons[weaponids[0]].tipvelocity = velocity * scale;
4764 weapons[weaponids[0]].missed = 1;
4765 weapons[weaponids[0]].hitsomething = 0;
4766 weapons[weaponids[0]].freetime = 0;
4767 weapons[weaponids[0]].firstfree = 1;
4768 weapons[weaponids[0]].physics = 1;
4771 weaponids[0] = weaponids[num_weapons];
4772 if (weaponstuck == num_weapons)
4776 for (unsigned i = 0; i < Person::players.size(); i++) {
4777 Person::players[i]->wentforweapon = 0;
4783 if (!dead && creature == wolftype) {
4784 award_bonus(0, Wolfbonus);
4787 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4788 award_bonus(id, touchofdeath);
4789 if (id != 0 && unconscioustime > .1) {
4797 emit_sound_at(breaksound, coords);
4800 if (skeleton.free == 1) {
4802 pause_sound(whooshsound);
4805 //If knocked over, open hands and close mouth
4806 if (righthandmorphend != 0)
4807 righthandmorphness = 0;
4808 righthandmorphend = 0;
4809 targetrighthandmorphness = 1;
4811 if (lefthandmorphend != 0)
4812 lefthandmorphness = 0;
4813 lefthandmorphend = 0;
4814 targetlefthandmorphness = 1;
4816 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4817 if (headmorphend != 0)
4820 targetheadmorphness = 1;
4824 skeleton.DoGravity(&scale);
4826 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4827 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4828 award_bonus(id, deepimpact);
4829 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4833 for (j = 0; j < skeleton.num_joints; j++) {
4834 average += skeleton.joints[j].position;
4838 coords += average * scale;
4839 for (j = 0; j < skeleton.num_joints; j++) {
4840 skeleton.joints[j].position -= average;
4842 average /= multiplier;
4844 //velocity=jointVel(groin)*scale;
4846 for (int i = 0; i < skeleton.num_joints; i++) {
4847 velocity += skeleton.joints[i].velocity * scale;
4849 velocity /= skeleton.num_joints;
4851 if (!isnormal(velocity.x) && velocity.x) {
4855 if (findLength(&average) < 10 && dead && skeleton.free) {
4856 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4857 if (skeleton.longdead > 2000) {
4858 if (skeleton.longdead > 6000) {
4860 pause_sound(whooshsound);
4865 if (dead == 2 && bloodloss < damagetolerance) {
4867 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4869 if (bloodtoggle && !bled) {
4870 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4872 if (bloodtoggle && !bled)
4873 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4874 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4875 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4876 float size = .2 * 1.2;
4879 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4883 if (dead == 2 && bloodloss >= damagetolerance) {
4885 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4888 if (bloodtoggle && !bled) {
4889 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4891 if (bloodtoggle && !bled)
4892 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4893 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4894 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4898 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4905 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4906 bool canrecover = 1;
4907 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4908 startpoint = coords;
4911 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4913 if (velocity.y < -30)
4915 for (i = 0; i < objects.numobjects; i++) {
4916 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4917 colviewer = startpoint;
4918 coltarget = endpoint;
4919 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4928 terrainnormal = jointPos(groin) - jointPos(abdomen);
4929 if (joint(groin).locked && joint(abdomen).locked) {
4930 terrainnormal = jointPos(groin) - jointPos(abdomen);
4931 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4933 if (joint(abdomen).locked && joint(neck).locked) {
4934 terrainnormal = jointPos(abdomen) - jointPos(neck);
4935 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4937 if (joint(groin).locked && joint(neck).locked) {
4938 terrainnormal = jointPos(groin) - jointPos(neck);
4939 middle = (jointPos(groin) + jointPos(neck)) / 2;
4941 Normalise(&terrainnormal);
4943 targetyaw = -asin(0 - terrainnormal.x);
4944 targetyaw *= 360 / 6.28;
4945 if (terrainnormal.z < 0)
4946 targetyaw = 180 - targetyaw;
4950 animTarget = flipanim;
4951 crouchtogglekeydown = 1;
4956 animCurrent = tempanim;
4960 for (int i = 0; i < skeleton.num_joints; i++) {
4961 tempanimation.position[i][0] = skeleton.joints[i].position;
4962 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4967 if (findLength(&average) < 10 && !dead && skeleton.free) {
4968 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4969 if (skeleton.longdead > (damage + 500) * 1.5) {
4971 pause_sound(whooshsound);
4977 terrainnormal = jointPos(groin) - jointPos(abdomen);
4978 if (joint(groin).locked && joint(abdomen).locked) {
4979 terrainnormal = jointPos(groin) - jointPos(abdomen);
4980 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4982 if (joint(abdomen).locked && joint(neck).locked) {
4983 terrainnormal = jointPos(abdomen) - jointPos(neck);
4984 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4986 if (joint(groin).locked && joint(neck).locked) {
4987 terrainnormal = jointPos(groin) - jointPos(neck);
4988 middle = (jointPos(groin) + jointPos(neck)) / 2;
4990 Normalise(&terrainnormal);
4992 targetyaw = -asin(0 - terrainnormal.x);
4993 targetyaw *= 360 / 6.28;
4994 if (terrainnormal.z < 0)
4995 targetyaw = 180 - targetyaw;
4998 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5001 if (skeleton.forward.y < 0) {
5002 animTarget = getupfrombackanim;
5006 if (skeleton.forward.y > -.3) {
5007 animTarget = getupfromfrontanim;
5015 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5016 animTarget = rollanim;
5017 targetyaw = lookyaw;
5034 if ( !leftkeydown && !rightkeydown)
5041 if (abs(targettilt2) > 50)
5043 animCurrent = tempanim;
5046 tilt2 = targettilt2;
5048 if (middle.y > 0 && animTarget != rollanim)
5049 targetoffset.y = middle.y + 1;
5051 for (int i = 0; i < skeleton.num_joints; i++) {
5052 tempanimation.position[i][0] = skeleton.joints[i].position;
5053 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5060 if (num_weapons > 0)
5061 if (weapons[0].getType() == staff)
5063 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5064 if (velocity.y > -30) {
5066 tempvelocity = velocity;
5067 Normalise(&tempvelocity);
5068 targetyaw = -asin(0 - tempvelocity.x);
5069 targetyaw *= 360 / 6.28;
5071 targetyaw = 180 - targetyaw;
5075 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5076 animTarget = rollanim;
5079 animTarget = backhandspringanim;
5085 emit_sound_at(movewhooshsound, coords, 128.);
5087 animCurrent = animTarget;
5088 frameCurrent = frameTarget - 1;
5100 if (skeleton.freefall == 0)
5105 if (aitype != passivetype || skeleton.free == 1)
5106 if (findLengthfast(&velocity) > .1)
5107 for (i = 0; i < objects.numobjects; i++) {
5108 if (objects.type[i] == firetype)
5109 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) {
5111 if (!objects.onfire[i]) {
5112 emit_sound_at(firestartsound, objects.position[i]);
5114 objects.onfire[i] = 1;
5117 if (objects.onfire[i]) {
5122 if (objects.type[i] == bushtype)
5123 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) {
5125 if (!objects.onfire[i]) {
5126 emit_sound_at(firestartsound, objects.position[i]);
5128 objects.onfire[i] = 1;
5132 if (objects.onfire[i]) {
5136 if (objects.messedwith[i] <= 0) {
5140 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5143 envsound[numenvsounds] = coords;
5144 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5145 envsoundlife[numenvsounds] = .4;
5150 if (environment == grassyenvironment)
5151 howmany = findLength(&velocity) * 4;
5152 if (environment == snowyenvironment)
5153 howmany = findLength(&velocity) * 2;
5155 if (environment != desertenvironment)
5156 for (j = 0; j < howmany; j++) {
5157 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5158 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5159 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5162 pos.x += float(abs(Random() % 100) - 50) / 200;
5163 pos.y += float(abs(Random() % 100) - 50) / 200;
5164 pos.z += float(abs(Random() % 100) - 50) / 200;
5165 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);
5166 Sprite::setLastSpriteSpecial(1);
5168 howmany = findLength(&velocity) * 4;
5170 if (environment == snowyenvironment)
5171 for (j = 0; j < howmany; j++) {
5172 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5173 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5174 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5177 pos.x += float(abs(Random() % 100) - 50) / 200;
5178 pos.y += float(abs(Random() % 100) - 50) / 200;
5179 pos.z += float(abs(Random() % 100) - 50) / 200;
5180 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5181 Sprite::setLastSpriteSpecial(2);
5184 objects.rotx[i] += velocity.x * multiplier * 6;
5185 objects.roty[i] += velocity.z * multiplier * 6;
5186 objects.messedwith[i] = .5;
5189 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5190 if (objects.pitch[i] == 0)
5193 tempcoord = coords - objects.position[i];
5194 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5195 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5196 tempcoord += objects.position[i];
5198 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]) {
5199 if (objects.messedwith[i] <= 0) {
5203 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5206 envsound[numenvsounds] = coords;
5207 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5208 envsoundlife[numenvsounds] = .4;
5213 if (environment == grassyenvironment)
5214 howmany = findLength(&velocity) * 4;
5215 if (environment == snowyenvironment)
5216 howmany = findLength(&velocity) * 2;
5218 if (environment != desertenvironment)
5219 for (j = 0; j < howmany; j++) {
5220 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5221 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5222 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5224 pos += velocity * .1;
5226 pos.x += float(abs(Random() % 100) - 50) / 150;
5227 pos.y += float(abs(Random() % 100) - 50) / 150;
5228 pos.z += float(abs(Random() % 100) - 50) / 150;
5229 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);
5230 Sprite::setLastSpriteSpecial(1);
5232 howmany = findLength(&velocity) * 4;
5234 if (environment == snowyenvironment)
5235 for (j = 0; j < howmany; j++) {
5236 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5237 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5238 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5240 pos += velocity * .1;
5242 pos.x += float(abs(Random() % 100) - 50) / 150;
5243 pos.y += float(abs(Random() % 100) - 50) / 150;
5244 pos.z += float(abs(Random() % 100) - 50) / 150;
5245 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5246 Sprite::setLastSpriteSpecial(2);
5249 objects.messedwith[i] = .5;
5254 if (!skeleton.free) {
5257 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5260 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5262 if (tutoriallevel == 1 && id != 0)
5264 if (play && aitype != playercontrolled) {
5265 int whichsound = -1;
5266 i = abs(Random() % 4);
5267 if (speechdelay <= 0) {
5268 if (creature == rabbittype) {
5270 whichsound = rabbitchitter;
5272 whichsound = rabbitchitter2;
5274 if (creature == wolftype) {
5276 whichsound = growlsound;
5278 whichsound = growl2sound;
5283 if (whichsound != -1) {
5284 emit_sound_at(whichsound, coords);
5288 if (animTarget == staggerbackhighanim)
5290 if (animTarget == staggerbackhardanim)
5292 staggerdelay -= multiplier;
5293 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5295 if (velocity.y < -30 && animTarget == jumpdownanim)
5297 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5298 animTarget = getIdle();
5302 weaponmissdelay -= multiplier;
5303 highreversaldelay -= multiplier;
5304 lowreversaldelay -= multiplier;
5305 lastcollide -= multiplier;
5306 skiddelay -= multiplier;
5307 if (!isnormal(velocity.x) && velocity.x) {
5310 if (!isnormal(targettilt) && targettilt) {
5313 if (!isnormal(targettilt2) && targettilt2) {
5316 if (!isnormal(targetyaw) && targetyaw) {
5320 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5321 //open hands and close mouth
5322 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5323 righthandmorphness = 0;
5324 righthandmorphend = 0;
5325 targetrighthandmorphness = 1;
5328 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5329 lefthandmorphness = 0;
5330 lefthandmorphend = 0;
5331 targetlefthandmorphness = 1;
5334 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5337 targetheadmorphness = 1;
5341 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) {
5342 //open hands and mouth
5343 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5344 righthandmorphness = 0;
5345 righthandmorphend = 0;
5346 targetrighthandmorphness = 1;
5349 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5350 lefthandmorphness = 0;
5351 lefthandmorphend = 0;
5352 targetlefthandmorphness = 1;
5355 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5358 targetheadmorphness = 1;
5362 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5363 //close hands and mouth
5364 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5365 righthandmorphness = 0;
5366 righthandmorphend = 1;
5367 targetrighthandmorphness = 1;
5370 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5371 lefthandmorphness = 0;
5372 lefthandmorphend = 1;
5373 targetlefthandmorphness = 1;
5376 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5379 targetheadmorphness = 1;
5383 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) {
5384 //close hands and yell
5385 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5386 righthandmorphness = 0;
5387 righthandmorphend = 1;
5388 targetrighthandmorphness = 1;
5391 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5392 lefthandmorphness = 0;
5393 lefthandmorphend = 1;
5394 targetlefthandmorphness = 1;
5397 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5400 targetheadmorphness = 1;
5407 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5408 (victim->aitype != searchtype) && (aitype != passivetype) &&
5409 (aitype != searchtype) && (victim->id < Person::players.size()) && (aitype != passivetype)) {
5410 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5414 if (!dead && animTarget != hurtidleanim)
5415 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5416 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5419 targetheadmorphness = 1;
5423 if (weaponactive != -1) {
5424 if (weapons[weaponids[weaponactive]].getType() != staff) {
5425 righthandmorphstart = 1;
5426 righthandmorphend = 1;
5428 if (weapons[weaponids[weaponactive]].getType() == staff) {
5429 righthandmorphstart = 2;
5430 righthandmorphend = 2;
5432 targetrighthandmorphness = 1;
5435 terrainnormal = terrain.getNormal(coords.x, coords.z);
5437 if (animation[animTarget].attack != reversal) {
5438 if (!isnormal(coords.x))
5446 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5447 facing = flatfacing;
5448 ReflectVector(&facing, terrainnormal);
5451 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5453 targettilt2 = -facing.y * 20;
5458 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5460 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5461 flatvelocity = velocity;
5463 flatvelspeed = findLength(&flatvelocity);
5464 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5465 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5470 if (targettilt > 25)
5472 if (targettilt < -25)
5476 if (targettilt2 > 45)
5478 if (targettilt2 < -45)
5480 if (abs(tilt2 - targettilt2) < multiplier * 400)
5481 tilt2 = targettilt2;
5482 else if (tilt2 > targettilt2) {
5483 tilt2 -= multiplier * 400;
5484 } else if (tilt2 < targettilt2) {
5485 tilt2 += multiplier * 400;
5487 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5494 if (!isnormal(targettilt) && targettilt) {
5497 if (!isnormal(targettilt2) && targettilt2) {
5502 if (animTarget == rabbittackleanim) {
5503 velocity += facing * multiplier * speed * 700 * scale;
5504 velspeed = findLength(&velocity);
5505 if (velspeed > speed * 65 * scale) {
5506 velocity /= velspeed;
5507 velspeed = speed * 65 * scale;
5508 velocity *= velspeed;
5510 velocity.y += gravity * multiplier * 20;
5511 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5512 velspeed = findLength(&velocity);
5513 velocity = flatfacing * velspeed;
5515 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5516 if (isRun() || animTarget == rabbitkickanim) {
5517 velocity += facing * multiplier * speed * 700 * scale;
5518 velspeed = findLength(&velocity);
5519 if (velspeed > speed * 45 * scale) {
5520 velocity /= velspeed;
5521 velspeed = speed * 45 * scale;
5522 velocity *= velspeed;
5524 velocity.y += gravity * multiplier * 20;
5525 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5526 velspeed = findLength(&velocity);
5527 if (velspeed < speed * 30 * scale)
5528 velspeed = speed * 30 * scale;
5529 velocity = flatfacing * velspeed;
5531 } else if (isRun()) {
5532 velocity += facing * multiplier * speed * 700 * scale;
5533 velspeed = findLength(&velocity);
5534 if (creature == rabbittype) {
5535 if (velspeed > speed * 55 * scale) {
5536 velocity /= velspeed;
5537 velspeed = speed * 55 * scale;
5538 velocity *= velspeed;
5541 if (creature == wolftype) {
5542 if (velspeed > speed * 75 * scale) {
5543 velocity /= velspeed;
5544 velspeed = speed * 75 * scale;
5545 velocity *= velspeed;
5548 velocity.y += gravity * multiplier * 20;
5549 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5550 velspeed = findLength(&velocity);
5551 velocity = flatfacing * velspeed;
5554 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5555 velocity += facing * multiplier * speed * 700 * scale;
5556 velspeed = findLength(&velocity);
5557 if (velspeed > speed * 45 * scale) {
5558 velocity /= velspeed;
5559 velspeed = speed * 45 * 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;
5568 if (animTarget == sneakanim || animTarget == walkanim) {
5569 velocity += facing * multiplier * speed * 700 * scale;
5570 velspeed = findLength(&velocity);
5571 if (velspeed > speed * 12 * scale) {
5572 velocity /= velspeed;
5573 velspeed = speed * 12 * scale;
5574 velocity *= velspeed;
5576 velocity.y += gravity * multiplier * 20;
5577 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5578 velspeed = findLength(&velocity);
5579 velocity = flatfacing * velspeed;
5582 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5583 velocity += facing * multiplier * speed * 700 * scale;
5584 velspeed = findLength(&velocity);
5585 if (velspeed > speed * 2 * scale) {
5586 velocity /= velspeed;
5587 velspeed = speed * 2 * scale;
5588 velocity *= velspeed;
5590 velocity.y += gravity * multiplier * 20;
5591 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5592 velspeed = findLength(&velocity);
5593 velocity = flatfacing * velspeed;
5597 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5598 velocity -= facing * multiplier * speed * 700 * scale;
5599 velspeed = findLength(&velocity);
5600 if (velspeed > speed * 2 * scale) {
5601 velocity /= velspeed;
5602 velspeed = speed * 2 * scale;
5603 velocity *= velspeed;
5605 velocity.y += gravity * multiplier * 20;
5606 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5607 velspeed = findLength(&velocity);
5608 velocity = flatfacing * velspeed * -1;
5611 if (animTarget == fightsidestep) {
5612 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5613 velspeed = findLength(&velocity);
5614 if (velspeed > speed * 12 * scale) {
5615 velocity /= velspeed;
5616 velspeed = speed * 12 * scale;
5617 velocity *= velspeed;
5619 velocity.y += gravity * multiplier * 20;
5620 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5621 velspeed = findLength(&velocity);
5622 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5625 if (animTarget == staggerbackhighanim) {
5626 coords -= facing * multiplier * speed * 16 * scale;
5629 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5630 coords -= facing * multiplier * speed * 20 * scale;
5634 if (animTarget == backhandspringanim) {
5635 //coords-=facing*multiplier*50*scale;
5636 velocity += facing * multiplier * speed * 700 * scale * -1;
5637 velspeed = findLength(&velocity);
5638 if (velspeed > speed * 50 * scale) {
5639 velocity /= velspeed;
5640 velspeed = speed * 50 * scale;
5641 velocity *= velspeed;
5643 velocity.y += gravity * multiplier * 20;
5644 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5645 velspeed = findLength(&velocity);
5646 velocity = flatfacing * velspeed * -1;
5648 if (animTarget == dodgebackanim) {
5649 //coords-=facing*multiplier*50*scale;
5650 velocity += facing * multiplier * speed * 700 * scale * -1;
5651 velspeed = findLength(&velocity);
5652 if (velspeed > speed * 60 * scale) {
5653 velocity /= velspeed;
5654 velspeed = speed * 60 * 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 == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5664 velspeed = findLength(&velocity);
5668 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5669 velocity.y += gravity * multiplier;
5672 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5673 coords += velocity * multiplier;
5675 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5676 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5679 if (animTarget == jumpupanim) {
5681 animTarget = getIdle();
5688 pause_sound(whooshsound);
5689 OPENAL_SetVolume(channels[whooshsound], 0);
5692 if (animTarget == jumpdownanim || isFlip()) {
5693 if (isFlip())jumppower = -4;
5694 animTarget = getLanding();
5695 emit_sound_at(landsound, coords, 128.);
5698 envsound[numenvsounds] = coords;
5699 envsoundvol[numenvsounds] = 16;
5700 envsoundlife[numenvsounds] = .4;
5706 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5707 coords.y += gravity * multiplier * 2;
5708 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5709 coords.y = terrain.getHeight(coords.x, coords.z);
5714 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)) {
5715 velspeed = findLength(&velocity);
5717 if (velspeed < multiplier * 300 * scale) {
5720 velocity -= velocity / velspeed * multiplier * 300 * scale;
5721 if (velspeed > 5 && (isLanding() || isLandhard())) {
5722 skiddingdelay += multiplier;
5723 if (skiddelay <= 0) {
5733 velspeed = findLength(&velocity);
5735 if (velspeed < multiplier * 600 * scale) {
5738 velocity -= velocity / velspeed * multiplier * 600 * scale;
5740 if (velspeed > 5 && (isLanding() || isLandhard())) {
5741 skiddingdelay += multiplier;
5742 if (skiddelay <= 0) {
5751 if (skiddingdelay < 0)
5752 skiddingdelay += multiplier;
5753 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5755 if (!onterrain || environment == grassyenvironment) {
5756 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5758 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5762 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5763 terrainnormal = victim->coords - coords;
5764 Normalise(&terrainnormal);
5765 targetyaw = -asin(0 - terrainnormal.x);
5766 targetyaw *= 360 / 6.28;
5767 if (terrainnormal.z < 0)
5768 targetyaw = 180 - targetyaw;
5769 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5772 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5773 targetyaw = victim->targetyaw;
5775 if (animTarget == rabbittacklinganim) {
5776 coords = victim->coords;
5779 skeleton.oldfree = skeleton.free;
5783 midterrain.x = terrain.size * terrain.scale / 2;
5784 midterrain.z = terrain.size * terrain.scale / 2;
5785 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5787 tempposit = coords - midterrain;
5789 Normalise(&tempposit);
5790 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5791 coords.x = tempposit.x + midterrain.x;
5792 coords.z = tempposit.z + midterrain.z;
5798 * inverse kinematics helper function
5800 void IKHelper(Person *p, float interp)
5802 XYZ point, newpoint, change, change2;
5803 float heightleft, heightright;
5805 // TODO: implement localToWorld and worldToLocal
5806 // but keep in mind it won't be the same math if player is ragdolled or something
5807 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5808 // then comb through code for places where to use it
5810 // point = localToWorld(jointPos(leftfoot))
5811 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5812 // adjust height of foot
5813 heightleft = terrain.getHeight(point.x, point.z) + .04;
5814 point.y = heightleft;
5815 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5816 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5817 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5818 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5819 // move ankle along with foot
5820 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5821 // average knee pos between old and new pos
5822 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5824 // do same as above for right leg
5825 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5826 heightright = terrain.getHeight(point.x, point.z) + .04;
5827 point.y = heightright;
5828 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5829 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5830 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5831 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5832 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5834 // fix up skeleton now that we've moved body parts?
5835 p->skeleton.DoConstraints(&p->coords, &p->scale);
5842 int Person::DrawSkeleton()
5844 int oldplayerdetail;
5845 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5846 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5856 glAlphaFunc(GL_GREATER, 0.0001);
5858 float terrainheight;
5862 if (!isnormal(tilt))
5864 if (!isnormal(tilt2))
5866 oldplayerdetail = playerdetail;
5868 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5871 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5874 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5879 if (playerdetail != oldplayerdetail) {
5881 normalsupdatedelay = 0;
5883 static float updatedelaychange;
5884 static float morphness;
5885 static float framemult;
5887 skeleton.FindForwards();
5888 if (howactive == typesittingwall) {
5889 skeleton.specialforward[1] = 0;
5890 skeleton.specialforward[1].z = 1;
5896 static int weaponattachmuscle;
5897 static int weaponrotatemuscle;
5898 static XYZ weaponpoint;
5899 static int start, endthing;
5900 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5901 if (!isSleeping() && !isSitting()) {
5902 // TODO: give these meaningful names
5903 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5904 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5905 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5906 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5908 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5910 if (creature == wolftype)
5914 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5915 IKHelper(this, target);
5916 if (creature == wolftype)
5917 IKHelper(this, target);
5920 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5921 IKHelper(this, 1 - target);
5922 if (creature == wolftype)
5923 IKHelper(this, 1 - target);
5927 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()))
5930 targetheadyaw = -targetyaw;
5931 targetheadpitch = 0;
5932 if (animation[animTarget].attack == 3)
5933 targetheadyaw += 180;
5935 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5936 skeleton.drawmodel.vertex[i] = 0;
5937 skeleton.drawmodel.vertex[i].y = 999;
5939 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5940 skeleton.drawmodellow.vertex[i] = 0;
5941 skeleton.drawmodellow.vertex[i].y = 999;
5943 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5944 skeleton.drawmodelclothes.vertex[i] = 0;
5945 skeleton.drawmodelclothes.vertex[i].y = 999;
5947 for (int i = 0; i < skeleton.num_muscles; i++) {
5948 // convenience renames
5949 const int p1 = skeleton.muscles[i].parent1->label;
5950 const int p2 = skeleton.muscles[i].parent2->label;
5952 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
5957 if (p1 == righthand || p2 == righthand) {
5958 morphness = righthandmorphness;
5959 start = righthandmorphstart;
5960 endthing = righthandmorphend;
5962 if (p1 == lefthand || p2 == lefthand) {
5963 morphness = lefthandmorphness;
5964 start = lefthandmorphstart;
5965 endthing = lefthandmorphend;
5967 if (p1 == head || p2 == head) {
5968 morphness = headmorphness;
5969 start = headmorphstart;
5970 endthing = headmorphend;
5972 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
5973 morphness = chestmorphness;
5974 start = chestmorphstart;
5975 endthing = chestmorphend;
5977 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
5978 morphness = tailmorphness;
5979 start = tailmorphstart;
5980 endthing = tailmorphend;
5983 skeleton.FindRotationMuscle(i, animTarget);
5984 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5985 glMatrixMode(GL_MODELVIEW);
5989 glRotatef(tilt2, 1, 0, 0);
5991 glRotatef(tilt, 0, 0, 1);
5994 glTranslatef(mid.x, mid.y, mid.z);
5996 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
5997 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
5999 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6000 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6002 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6003 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6005 if (playerdetail || skeleton.free == 3) {
6006 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6007 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6008 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6009 glMatrixMode(GL_MODELVIEW);
6011 if (p1 == abdomen || p2 == abdomen)
6012 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6013 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6014 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6015 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6016 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6017 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6018 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6019 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6020 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6021 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6022 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6023 if (p1 == head || p2 == head)
6024 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6025 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6026 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6027 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6028 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6029 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6030 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6034 if (!playerdetail || skeleton.free == 3) {
6035 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6036 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6037 glMatrixMode(GL_MODELVIEW);
6039 if (p1 == abdomen || p2 == abdomen)
6040 glTranslatef(v0.x * proportionbody.x,
6041 v0.y * proportionbody.y,
6042 v0.z * proportionbody.z);
6043 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6044 glTranslatef(v0.x * proportionarms.x,
6045 v0.y * proportionarms.y,
6046 v0.z * proportionarms.z);
6047 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6048 glTranslatef(v0.x * proportionlegs.x,
6049 v0.y * proportionlegs.y,
6050 v0.z * proportionlegs.z);
6051 if (p1 == head || p2 == head)
6052 glTranslatef(v0.x * proportionhead.x,
6053 v0.y * proportionhead.y,
6054 v0.z * proportionhead.z);
6056 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6057 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6058 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6059 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6065 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6066 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6068 glMatrixMode(GL_MODELVIEW);
6072 glRotatef(tilt2, 1, 0, 0);
6074 glRotatef(tilt, 0, 0, 1);
6075 glTranslatef(mid.x, mid.y, mid.z);
6076 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6077 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6079 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6080 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6082 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6083 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6085 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6086 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6087 glMatrixMode(GL_MODELVIEW);
6089 if (p1 == abdomen || p2 == abdomen)
6090 glTranslatef(v0.x * proportionbody.x,
6091 v0.y * proportionbody.y,
6092 v0.z * proportionbody.z);
6093 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6094 glTranslatef(v0.x * proportionarms.x,
6095 v0.y * proportionarms.y,
6096 v0.z * proportionarms.z);
6097 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6098 glTranslatef(v0.x * proportionlegs.x,
6099 v0.y * proportionlegs.y,
6100 v0.z * proportionlegs.z);
6101 if (p1 == head || p2 == head)
6102 glTranslatef(v0.x * proportionhead.x,
6103 v0.y * proportionhead.y,
6104 v0.z * proportionhead.z);
6105 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6106 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6107 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6108 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6113 updatedelay = 1 + (float)(Random() % 100) / 1000;
6115 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6116 normalsupdatedelay = 1;
6117 if (playerdetail || skeleton.free == 3)
6118 skeleton.drawmodel.CalculateNormals(0);
6119 if (!playerdetail || skeleton.free == 3)
6120 skeleton.drawmodellow.CalculateNormals(0);
6121 if (skeleton.clothes)
6122 skeleton.drawmodelclothes.CalculateNormals(0);
6124 if (playerdetail || skeleton.free == 3)
6125 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6126 if (!playerdetail || skeleton.free == 3)
6127 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6128 if (skeleton.clothes) {
6129 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6134 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6135 if (updatedelaychange > -realmultiplier * 30)
6136 updatedelaychange = -realmultiplier * 30;
6137 if (updatedelaychange > -framemult * 4)
6138 updatedelaychange = -framemult * 4;
6139 if (skeleton.free == 1)
6140 updatedelaychange *= 6;
6142 updatedelaychange *= 8;
6143 updatedelay += updatedelaychange;
6145 glMatrixMode(GL_MODELVIEW);
6148 glTranslatef(coords.x, coords.y - .02, coords.z);
6150 glTranslatef(coords.x, coords.y - .02, coords.z);
6152 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6154 glRotatef(yaw, 0, 1, 0);
6157 glColor4f(.4, 1, .4, 1);
6158 glDisable(GL_LIGHTING);
6159 glDisable(GL_TEXTURE_2D);
6162 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6163 XYZ &v0 = skeleton.drawmodel.vertex[i];
6164 glVertex3f(v0.x, v0.y, v0.z);
6170 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6171 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6172 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6173 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6174 glVertex3f(v0.x, v0.y, v0.z);
6175 glVertex3f(v1.x, v1.y, v1.z);
6176 glVertex3f(v1.x, v1.y, v1.z);
6177 glVertex3f(v2.x, v2.y, v2.z);
6178 glVertex3f(v2.x, v2.y, v2.z);
6179 glVertex3f(v0.x, v0.y, v0.z);
6185 terrainlight = terrain.getLighting(coords.x, coords.z);
6186 distance = distsq(&viewer, &coords);
6187 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6191 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6192 if (terrainheight < 1)
6194 if (terrainheight > 1.7)
6195 terrainheight = 1.7;
6198 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6199 glDisable(GL_BLEND);
6200 glAlphaFunc(GL_GREATER, 0.0001);
6201 glEnable(GL_TEXTURE_2D);
6203 glDisable(GL_TEXTURE_2D);
6204 glColor4f(.7, .35, 0, .5);
6206 glEnable(GL_LIGHTING);
6209 if (tutoriallevel && id != 0) {
6210 glColor4f(.7, .7, .7, 0.6);
6212 glEnable(GL_LIGHTING);
6214 if (canattack && cananger)
6215 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6216 glDisable(GL_TEXTURE_2D);
6217 glColor4f(1, 0, 0, 0.8);
6219 glMatrixMode(GL_TEXTURE);
6221 glTranslatef(0, -smoketex, 0);
6222 glTranslatef(-smoketex, 0, 0);
6226 if ((tutoriallevel && id != 0))
6227 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6229 skeleton.drawmodel.draw();
6232 if (!playerdetail) {
6233 if ((tutoriallevel && id != 0))
6234 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6236 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6239 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6240 if (tutoriallevel && id != 0) {
6242 glMatrixMode(GL_MODELVIEW);
6243 glEnable(GL_TEXTURE_2D);
6244 glColor4f(.7, .7, .7, 0.6);
6246 glEnable(GL_LIGHTING);
6248 if (canattack && cananger)
6249 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6250 glDisable(GL_TEXTURE_2D);
6251 glColor4f(1, 0, 0, 0.8);
6253 glMatrixMode(GL_TEXTURE);
6255 glTranslatef(0, -smoketex * .6, 0);
6256 glTranslatef(smoketex * .6, 0, 0);
6259 if ((tutoriallevel && id != 0))
6260 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6262 skeleton.drawmodel.draw();
6265 if (!playerdetail) {
6266 if ((tutoriallevel && id != 0))
6267 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6269 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6274 if (tutoriallevel && id != 0) {
6276 glMatrixMode(GL_MODELVIEW);
6277 glEnable(GL_TEXTURE_2D);
6279 if (skeleton.clothes) {
6283 skeleton.drawmodelclothes.draw();
6285 skeleton.drawmodelclothes.drawimmediate();
6291 if (num_weapons > 0) {
6292 for (k = 0; k < num_weapons; k++) {
6294 if (weaponactive == k) {
6295 if (weapons[i].getType() != staff) {
6296 for (j = 0; j < skeleton.num_muscles; j++) {
6297 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6298 weaponattachmuscle = j;
6301 for (j = 0; j < skeleton.num_muscles; j++) {
6302 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) {
6303 weaponrotatemuscle = j;
6306 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6307 if (creature == wolftype)
6308 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6310 if (weapons[i].getType() == staff) {
6311 for (j = 0; j < skeleton.num_muscles; j++) {
6312 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6313 weaponattachmuscle = j;
6316 for (j = 0; j < skeleton.num_muscles; j++) {
6317 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) {
6318 weaponrotatemuscle = j;
6321 //weaponpoint=jointPos(rightwrist);
6322 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6323 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6324 XYZ tempnormthing, vec1, vec2;
6325 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6326 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6327 CrossProduct(&vec1, &vec2, &tempnormthing);
6328 Normalise(&tempnormthing);
6329 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6330 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6333 if (weaponactive != k && weaponstuck != k) {
6334 if (weapons[i].getType() == knife)
6335 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6336 if (weapons[i].getType() == sword)
6337 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6338 if (weapons[i].getType() == staff)
6339 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6340 for (j = 0; j < skeleton.num_muscles; j++) {
6341 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) {
6342 weaponrotatemuscle = j;
6346 if (weaponstuck == k) {
6347 if (weaponstuckwhere == 0)
6348 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6350 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6351 for (j = 0; j < skeleton.num_muscles; j++) {
6352 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) {
6353 weaponrotatemuscle = j;
6357 if (skeleton.free) {
6358 weapons[i].position = weaponpoint * scale + coords;
6359 weapons[i].bigrotation = 0;
6360 weapons[i].bigtilt = 0;
6361 weapons[i].bigtilt2 = 0;
6363 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;
6364 weapons[i].bigrotation = yaw;
6365 weapons[i].bigtilt = tilt;
6366 weapons[i].bigtilt2 = tilt2;
6368 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6369 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6370 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6371 if (weaponactive == k) {
6372 if (weapons[i].getType() == knife) {
6373 weapons[i].smallrotation = 180;
6374 weapons[i].smallrotation2 = 0;
6375 if (isCrouch() || wasCrouch()) {
6376 weapons[i].smallrotation2 = 20;
6378 if (animTarget == hurtidleanim) {
6379 weapons[i].smallrotation2 = 50;
6381 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6382 XYZ temppoint1, temppoint2, tempforward;
6385 temppoint1 = jointPos(righthand);
6386 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6387 distance = findDistance(&temppoint1, &temppoint2);
6388 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6389 weapons[i].rotation2 *= 360 / 6.28;
6392 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6393 weapons[i].rotation1 *= 360 / 6.28;
6394 weapons[i].rotation3 = 0;
6395 weapons[i].smallrotation = -90;
6396 weapons[i].smallrotation2 = 0;
6397 if (temppoint1.x > temppoint2.x)
6398 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6400 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6401 XYZ temppoint1, temppoint2, tempforward;
6404 temppoint1 = jointPos(righthand);
6405 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6406 distance = findDistance(&temppoint1, &temppoint2);
6407 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6408 weapons[i].rotation2 *= 360 / 6.28;
6411 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6412 weapons[i].rotation1 *= 360 / 6.28;
6413 weapons[i].rotation3 = 0;
6414 weapons[i].smallrotation = 90;
6415 weapons[i].smallrotation2 = 0;
6416 if (temppoint1.x > temppoint2.x)
6417 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6419 if (animTarget == knifethrowanim) {
6420 weapons[i].smallrotation = 90;
6421 //weapons[i].smallrotation2=-90;
6422 weapons[i].smallrotation2 = 0;
6423 weapons[i].rotation1 = 0;
6424 weapons[i].rotation2 = 0;
6425 weapons[i].rotation3 = 0;
6427 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6428 weapons[i].smallrotation = -90;
6429 weapons[i].rotation1 = 0;
6430 weapons[i].rotation2 = 0;
6431 weapons[i].rotation3 = 0;
6434 if (weapons[i].getType() == sword) {
6435 weapons[i].smallrotation = 0;
6436 weapons[i].smallrotation2 = 0;
6437 if (animTarget == knifethrowanim) {
6438 weapons[i].smallrotation = -90;
6439 weapons[i].smallrotation2 = 0;
6440 weapons[i].rotation1 = 0;
6441 weapons[i].rotation2 = 0;
6442 weapons[i].rotation3 = 0;
6444 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)) {
6445 XYZ temppoint1, temppoint2, tempforward;
6448 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6449 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6450 distance = findDistance(&temppoint1, &temppoint2);
6451 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6452 weapons[i].rotation2 *= 360 / 6.28;
6455 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6456 weapons[i].rotation1 *= 360 / 6.28;
6457 weapons[i].rotation3 = 0;
6458 weapons[i].smallrotation = 90;
6459 weapons[i].smallrotation2 = 0;
6460 if (temppoint1.x > temppoint2.x)
6461 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6464 if (weapons[i].getType() == staff) {
6465 weapons[i].smallrotation = 100;
6466 weapons[i].smallrotation2 = 0;
6467 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6468 XYZ temppoint1, temppoint2, tempforward;
6471 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6472 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6473 distance = findDistance(&temppoint1, &temppoint2);
6474 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6475 weapons[i].rotation2 *= 360 / 6.28;
6478 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6479 weapons[i].rotation1 *= 360 / 6.28;
6480 weapons[i].rotation3 = 0;
6481 weapons[i].smallrotation = 90;
6482 weapons[i].smallrotation2 = 0;
6483 if (temppoint1.x > temppoint2.x)
6484 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6488 if (weaponactive != k && weaponstuck != k) {
6489 if (weapons[i].getType() == knife) {
6490 weapons[i].smallrotation = -70;
6491 weapons[i].smallrotation2 = 10;
6493 if (weapons[i].getType() == sword) {
6494 weapons[i].smallrotation = -100;
6495 weapons[i].smallrotation2 = -8;
6497 if (weapons[i].getType() == staff) {
6498 weapons[i].smallrotation = -100;
6499 weapons[i].smallrotation2 = -8;
6502 if (weaponstuck == k) {
6503 if (weaponstuckwhere == 0)
6504 weapons[i].smallrotation = 180;
6506 weapons[i].smallrotation = 0;
6507 weapons[i].smallrotation2 = 10;
6516 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isFlip() || isWallJump())
6518 if (animCurrent != animTarget)
6520 if (skeleton.free == 2)
6529 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6532 static float distance;
6533 static float olddistance;
6534 static int intersecting;
6535 static int firstintersecting;
6538 static XYZ start, end;
6539 static float slopethreshold = -.4;
6541 firstintersecting = -1;
6545 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6548 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6549 for (i = 0; i < 4; i++) {
6550 for (j = 0; j < model->TriangleNum; j++) {
6551 if (model->facenormals[j].y <= slopethreshold) {
6553 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)));
6554 if (distance < radius) {
6555 point = *p1 - model->facenormals[j] * distance;
6556 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]]))
6559 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6560 &model->vertex[model->Triangles[j].vertex[1]],
6563 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6564 &model->vertex[model->Triangles[j].vertex[2]],
6567 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6568 &model->vertex[model->Triangles[j].vertex[2]],
6571 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6575 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)) {
6576 p1->y = point.y + radius;
6577 if ((animTarget == jumpdownanim || isFlip())) {
6578 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6581 if (animTarget == jumpupanim) {
6583 animTarget = getIdle();
6590 pause_sound(whooshsound);
6591 OPENAL_SetVolume(channels[whooshsound], 0);
6594 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6597 animTarget = getLanding();
6598 emit_sound_at(landsound, coords, 128.);
6601 envsound[numenvsounds] = coords;
6602 envsoundvol[numenvsounds] = 16;
6603 envsoundlife[numenvsounds] = .4;
6611 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6612 olddistance = distance;
6613 firstintersecting = j;
6618 for (j = 0; j < model->TriangleNum; j++) {
6619 if (model->facenormals[j].y > slopethreshold) {
6622 start.y -= radius / 4;
6623 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6624 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6625 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6626 distance = abs((model->facenormals[j].x * start.x)
6627 + (model->facenormals[j].y * start.y)
6628 + (model->facenormals[j].z * start.z)
6629 - ((model->facenormals[j].x * v0.x)
6630 + (model->facenormals[j].y * v0.y)
6631 + (model->facenormals[j].z * v0.z)));
6632 if (distance < radius * .5) {
6633 point = start - model->facenormals[j] * distance;
6634 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6637 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6639 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6641 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6643 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6644 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6646 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6647 if (findLengthfast(&start) < findLengthfast(&velocity))
6650 *p1 += model->facenormals[j] * (distance - radius * .5);
6653 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6654 olddistance = distance;
6655 firstintersecting = j;
6662 *p = DoRotation(*p, 0, *rotate, 0);
6665 *p1 = DoRotation(*p1, 0, *rotate, 0);
6667 return firstintersecting;