2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation.h"
29 extern float multiplier;
30 extern Terrain terrain;
32 extern int environment;
34 extern FRUSTUM frustum;
36 extern float realmultiplier;
38 extern float slomodelay;
39 extern bool cellophane;
40 extern float texdetail;
41 extern float realtexdetail;
42 extern GLubyte bloodText[512 * 512 * 3];
43 extern GLubyte wolfbloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern float flashamount, flashr, flashg, flashb;
57 extern int flashdelay;
58 extern bool showpoints;
59 extern bool immediate;
61 extern bool tilt2weird;
62 extern bool tiltweird;
64 extern bool proportionweird;
65 extern bool vertexweird[6];
66 extern XYZ envsound[30];
67 extern float envsoundvol[30];
68 extern float envsoundlife[30];
69 extern int numenvsounds;
70 extern int tutoriallevel;
71 extern float smoketex;
72 extern int tutorialstage;
73 extern bool reversaltrain;
74 extern bool canattack;
76 extern float damagedealt;
78 extern float hostiletime;
80 extern int indialogue;
82 extern bool gamestarted;
84 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
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 = skeleton.joints[howmany].velocity;
165 flatfacing = skeleton.joints[howmany].position * scale + coords;
167 flatvelocity = velocity;
168 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
170 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
175 emit_sound_at(firestartsound, coords);
177 emit_stream_at(stream_firesound, coords);
185 * idle animation for this creature (depending on status)
187 int Person::getIdle()
189 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
191 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
192 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
193 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
194 victim->id < Person::players.size())) {
195 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
196 if (creature == rabbittype)
197 return fightidleanim;
198 if (creature == wolftype)
201 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
202 if (weapons[weaponids[weaponactive]].getType() == knife)
203 return knifefightidleanim;
204 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
205 return swordfightidlebothanim;
206 if (weapons[weaponids[weaponactive]].getType() == sword)
207 return swordfightidleanim;
208 if (weapons[weaponids[weaponactive]].getType() == staff)
209 return swordfightidleanim;
211 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
212 return fightsidestep;
214 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
216 if (howactive == typesitting) return sitanim;
217 if (howactive == typesittingwall) return sitwallanim;
218 if (howactive == typesleeping) return sleepanim;
219 if (howactive == typedead1) return dead1anim;
220 if (howactive == typedead2) return dead2anim;
221 if (howactive == typedead3) return dead3anim;
222 if (howactive == typedead4) return dead4anim;
223 if (creature == rabbittype) return bounceidleanim;
224 if (creature == wolftype) return wolfidle;
229 * crouch animation for this creature
231 int Person::getCrouch()
233 if (creature == rabbittype)
235 if (creature == wolftype)
236 return wolfcrouchanim;
241 * running animation for this creature (can be upright or all fours)
245 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
247 if (creature == wolftype && (!superruntoggle))
250 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
251 return rabbitrunninganim;
252 if (creature == wolftype && (superruntoggle))
253 return wolfrunninganim;
259 int Person::getStop()
261 if (creature == rabbittype)
263 if (creature == wolftype)
270 int Person::getLanding()
272 if (creature == rabbittype)
274 if (creature == wolftype)
281 int Person::getLandhard()
283 if (creature == rabbittype)
285 if (creature == wolftype)
286 return wolflandhardanim;
293 * Person::DoAnimations
296 SolidHitBonus(int playerid)
298 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
299 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
301 award_bonus(playerid, solidhit);
305 * spawns blood effects
307 void Person::DoBlood(float howmuch, int which)
309 // FIXME: should abstract out inputs
310 static int bleedxint, bleedyint;
312 if (bloodtoggle && tutoriallevel != 1) {
313 if (bleeding <= 0 && spurt) {
315 for (int i = 0; i < 3; i++) {
316 // emit blood particles
319 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
320 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
321 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
322 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
325 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
326 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
327 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
328 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
331 if (Random() % 2 == 0) // 50% chance
332 for (int i = 0; i < 3; i++) {
333 if (Random() % 2 != 0) {
334 // emit teeth particles
337 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
338 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
341 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
342 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
346 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
348 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
350 Sprite::setLastSpriteSpecial(3); // sets it to teeth
355 // FIXME: manipulating attributes
356 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
359 if (creature == rabbittype)
360 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) {
361 bleedxint = abs(Random() % 512);
362 bleedyint = abs(Random() % 512);
364 if (creature == wolftype)
365 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) {
366 bleedxint = abs(Random() % 512);
367 bleedyint = abs(Random() % 512);
371 bleedy /= realtexdetail;
372 bleedx /= realtexdetail;
373 direction = abs(Random() % 2) * 2 - 1;
382 * spawns big blood effects and ???
383 * modifies character's skin texture
385 void Person::DoBloodBig(float howmuch, int which)
387 static int bleedxint, bleedyint, i, j;
389 if (howmuch && id == 0)
392 if (tutoriallevel != 1 || id == 0)
393 if (aitype != playercontrolled && howmuch > 0) {
397 // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
398 if (creature == wolftype) {
399 int i = abs(Random() % 2);
401 whichsound = snarlsound;
403 whichsound = snarl2sound;
404 envsound[numenvsounds] = coords;
405 envsoundvol[numenvsounds] = 16;
406 envsoundlife[numenvsounds] = .4;
409 if (creature == rabbittype) {
410 int i = abs(Random() % 2);
412 whichsound = rabbitpainsound;
413 if (i == 1 && howmuch >= 2)
414 whichsound = rabbitpain1sound;
415 envsound[numenvsounds] = coords;
416 envsoundvol[numenvsounds] = 16;
417 envsoundlife[numenvsounds] = .4;
421 if (whichsound != -1)
422 emit_sound_at(whichsound, coords);
425 if (id == 0 && howmuch > 0) {
426 // FIXME: manipulating attributes
434 if (bloodtoggle && decals && tutoriallevel != 1) {
435 if (bleeding <= 0 && spurt) {
437 for (int i = 0; i < 3; i++) {
438 // emit blood particles
439 // FIXME: copypaste from above
442 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
443 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
444 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
445 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
448 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
449 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
450 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
451 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
456 // weird texture manipulation code follows.
457 // looks like this is painting blood onto the character's skin texture
458 // FIXME: surely there's a better way
460 int offsetx = 0, offsety = 0;
462 offsety = Random() % 40;
463 offsetx = abs(Random() % 60);
465 if (which == 190 || which == 185) {
466 offsety = Random() % 40;
467 offsetx = abs(Random() % 100) - 20;
470 offsety = Random() % 10;
471 offsetx = Random() % 10;
474 offsety = Random() % 20;
475 offsetx = Random() % 20;
477 if (which == 220 || which == 215) {
487 if (creature == rabbittype)
488 for (i = 0; i < 512; i++) {
489 for (j = 0; j < 512; j++) {
490 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
491 if (i < startx) startx = i;
492 if (j < starty) starty = j;
493 if (i > endx) endx = i;
494 if (j > endy) endy = j;
498 if (creature == wolftype)
499 for (i = 0; i < 512; i++) {
500 for (j = 0; j < 512; j++) {
501 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
502 if (i < startx) startx = i;
503 if (j < starty) starty = j;
504 if (i > endx) endx = i;
505 if (j > endy) endy = j;
515 if (startx < 0) startx = 0;
516 if (starty < 0) starty = 0;
517 if (endx > 512 - 1) endx = 512 - 1;
518 if (endy > 512 - 1) endy = 512 - 1;
519 if (endx < startx) endx = startx;
520 if (endy < starty) endy = starty;
522 startx /= realtexdetail;
523 starty /= realtexdetail;
524 endx /= realtexdetail;
525 endy /= realtexdetail;
527 int texdetailint = realtexdetail;
529 if (creature == rabbittype)
530 for (i = startx; i < endx; i++) {
531 for (j = starty; j < endy; j++) {
532 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) {
533 color = Random() % 85 + 170;
534 where = i * skeleton.skinsize * 3 + j * 3;
535 if (skeleton.skinText[where + 0] > color / 2)
536 skeleton.skinText[where + 0] = color / 2;
537 skeleton.skinText[where + 1] = 0;
538 skeleton.skinText[where + 2] = 0;
542 if (creature == wolftype)
543 for (i = startx; i < endx; i++) {
544 for (j = starty; j < endy; j++) {
545 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) {
546 color = Random() % 85 + 170;
547 where = i * skeleton.skinsize * 3 + j * 3;
548 if (skeleton.skinText[where + 0] > color / 2)
549 skeleton.skinText[where + 0] = color / 2;
550 skeleton.skinText[where + 1] = 0;
551 skeleton.skinText[where + 2] = 0;
555 skeleton.drawmodel.textureptr.bind();
560 if (creature == rabbittype)
561 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) {
562 bleedxint = abs(Random() % 512);
563 bleedyint = abs(Random() % 512);
565 if (creature == wolftype)
566 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) {
567 bleedxint = abs(Random() % 512);
568 bleedyint = abs(Random() % 512);
570 bleedy = bleedxint + offsetx;
571 bleedx = bleedyint + offsety;
572 bleedy /= realtexdetail;
573 bleedx /= realtexdetail;
578 if (bleedx > skeleton.skinsize - 1)
579 bleedx = skeleton.skinsize - 1;
580 if (bleedy > skeleton.skinsize - 1)
581 bleedy = skeleton.skinsize - 1;
582 direction = abs(Random() % 2) * 2 - 1;
585 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
586 deathbleeding += bleeding;
587 bloodloss += bleeding * 3;
589 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
590 if (abs(Random() % 2) == 0) {
591 aitype = gethelptype;
594 aitype = attacktypecutoff;
602 * similar to DoBloodBig
604 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
608 static XYZ startpoint, endpoint, colpoint, movepoint;
609 static float rotationpoint;
611 static XYZ p1, p2, p3, p0;
615 float coordsx, coordsy;
618 if (bloodtoggle && decals && tutoriallevel != 1) {
621 where = DoRotation(where, 0, -yaw, 0);
629 // ray testing for a tri in the character model
630 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
631 if (whichtri != -1) {
632 // low level geometry math
634 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
635 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
636 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
638 CrossProduct(p2-p1,p3-p1,&N);
639 CrossProduct(p0-p1,p3-p1,&temp);
640 s = dotproduct(&temp,&N)/findLength(&N);
641 CrossProduct(p2-p1,p1-p0,&temp);
642 t = dotproduct(&temp,&N)/findLength(&N);
645 bary.x = distsq(&p0, &p1);
646 bary.y = distsq(&p0, &p2);
647 bary.z = distsq(&p0, &p3);
649 total = bary.x + bary.y + bary.z;
658 total = bary.x + bary.y + bary.z;
664 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
665 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
666 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
667 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
668 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
669 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
670 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;
671 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;
673 //coordsx=skeleton.drawmodel.Triangles[whichtri].gx[1];
674 //coordsy=skeleton.drawmodel.Triangles[whichtri].gy[1];
676 if (bleeding <= 0 && spurt) {
678 for (int i = 0; i < 3; i++) {
679 // emit blood particles
680 // FIXME: more copypaste code
683 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
684 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
685 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
686 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
689 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
690 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
691 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
692 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
697 // texture manipulation follows
699 int offsetx = 0, offsety = 0;
700 offsetx = (1 + coordsy) * 512 - 291;
701 offsety = coordsx * 512 - 437;
708 if (creature == rabbittype)
709 for (i = 0; i < 512; i++) {
710 for (j = 0; j < 512; j++) {
711 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
712 if (i < startx) startx = i;
713 if (j < starty) starty = j;
714 if (i > endx) endx = i;
715 if (j > endy) endy = j;
719 if (creature == wolftype)
720 for (i = 0; i < 512; i++) {
721 for (j = 0; j < 512; j++) {
722 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
723 if (i < startx) startx = i;
724 if (j < starty) starty = j;
725 if (i > endx) endx = i;
726 if (j > endy) endy = j;
735 if (startx < 0) startx = 0;
736 if (starty < 0) starty = 0;
737 if (endx > 512 - 1) endx = 512 - 1;
738 if (endy > 512 - 1) endy = 512 - 1;
739 if (endx < startx) endx = startx;
740 if (endy < starty) endy = starty;
742 startx /= realtexdetail;
743 starty /= realtexdetail;
744 endx /= realtexdetail;
745 endy /= realtexdetail;
747 int texdetailint = realtexdetail;
749 if (creature == rabbittype)
750 for (i = startx; i < endx; i++) {
751 for (j = starty; j < endy; j++) {
752 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
753 color = Random() % 85 + 170;
754 where = i * skeleton.skinsize * 3 + j * 3;
755 if (skeleton.skinText[where + 0] > color / 2)
756 skeleton.skinText[where + 0] = color / 2;
757 skeleton.skinText[where + 1] = 0;
758 skeleton.skinText[where + 2] = 0;
759 } 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) {
760 color = Random() % 85 + 170;
761 where = i * skeleton.skinsize * 3 + j * 3;
762 if (skeleton.skinText[where + 0] > color / 2)
763 skeleton.skinText[where + 0] = color / 2;
764 skeleton.skinText[where + 1] = 0;
765 skeleton.skinText[where + 2] = 0;
769 if (creature == wolftype)
770 for (i = startx; i < endx; i++) {
771 for (j = starty; j < endy; j++) {
772 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) {
773 color = Random() % 85 + 170;
774 where = i * skeleton.skinsize * 3 + j * 3;
775 if (skeleton.skinText[where + 0] > color / 2)
776 skeleton.skinText[where + 0] = color / 2;
777 skeleton.skinText[where + 1] = 0;
778 skeleton.skinText[where + 2] = 0;
779 } 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) {
780 color = Random() % 85 + 170;
781 where = i * skeleton.skinsize * 3 + j * 3;
782 if (skeleton.skinText[where + 0] > color / 2)
783 skeleton.skinText[where + 0] = color / 2;
784 skeleton.skinText[where + 1] = 0;
785 skeleton.skinText[where + 2] = 0;
789 skeleton.drawmodel.textureptr.bind();
792 bleedy = (1 + coordsy) * 512;
793 bleedx = coordsx * 512;
794 bleedy /= realtexdetail;
795 bleedx /= realtexdetail;
800 if (bleedx > skeleton.skinsize - 1)
801 bleedx = skeleton.skinsize - 1;
802 if (bleedy > skeleton.skinsize - 1)
803 bleedy = skeleton.skinsize - 1;
804 direction = abs(Random() % 2) * 2 - 1;
809 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
810 deathbleeding += bleeding;
811 bloodloss += bleeding * 3;
813 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
814 if (abs(Random() % 2) == 0) {
815 aitype = gethelptype;
818 aitype = attacktypecutoff;
829 * guessing this performs a reversal
831 void Person::Reverse()
833 if (!((victim->aitype == playercontrolled
835 || staggerdelay <= 0)
836 && victim->animTarget != jumpupanim
837 && victim->animTarget != jumpdownanim
838 && (tutoriallevel != 1 || cananger)
842 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
843 && (victim->id != 0 || difficulty >= 2)
844 && (creature != wolftype || victim->creature == wolftype))
847 if (animTarget == sweepanim) {
848 animTarget = sweepreversedanim;
849 animCurrent = sweepreversedanim;
850 victim->animCurrent = sweepreversalanim;
851 victim->animTarget = sweepreversalanim;
853 if (animTarget == spinkickanim) {
854 animTarget = spinkickreversedanim;
855 animCurrent = spinkickreversedanim;
856 victim->animCurrent = spinkickreversalanim;
857 victim->animTarget = spinkickreversalanim;
859 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
860 if (animTarget == rabbittacklinganim) {
863 victim->frameCurrent = 6;
864 victim->frameTarget = 7;
866 animTarget = upunchreversedanim;
867 animCurrent = upunchreversedanim;
868 victim->animCurrent = upunchreversalanim;
869 victim->animTarget = upunchreversalanim;
871 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
872 if (victim->weaponactive != -1) {
873 victim->throwtogglekeydown = 1;
874 XYZ tempVelocity = victim->velocity * .2;
875 if (tempVelocity.x == 0)
877 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
878 victim->num_weapons--;
879 if (victim->num_weapons) {
880 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
881 if (victim->weaponstuck == victim->num_weapons)
882 victim->weaponstuck = 0;
885 victim->weaponactive = -1;
886 for (unsigned j = 0; j < Person::players.size(); j++) {
887 Person::players[j]->wentforweapon = 0;
891 animTarget = staffhitreversedanim;
892 animCurrent = staffhitreversedanim;
893 victim->animCurrent = staffhitreversalanim;
894 victim->animTarget = staffhitreversalanim;
896 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
897 if (victim->weaponactive != -1) {
898 victim->throwtogglekeydown = 1;
899 XYZ tempVelocity = victim->velocity * .2;
900 if (tempVelocity.x == 0)
902 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
903 victim->num_weapons--;
904 if (victim->num_weapons) {
905 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
906 if (victim->weaponstuck == victim->num_weapons)
907 victim->weaponstuck = 0;
910 victim->weaponactive = -1;
911 for (unsigned j = 0; j < Person::players.size(); j++) {
912 Person::players[j]->wentforweapon = 0;
915 animTarget = staffspinhitreversedanim;
916 animCurrent = staffspinhitreversedanim;
917 victim->animCurrent = staffspinhitreversalanim;
918 victim->animTarget = staffspinhitreversalanim;
920 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
921 if (victim->weaponactive != -1) {
922 victim->throwtogglekeydown = 1;
923 XYZ tempVelocity = victim->velocity * .2;
924 if (tempVelocity.x == 0)
926 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
927 victim->num_weapons--;
928 if (victim->num_weapons) {
929 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
930 if (victim->weaponstuck == victim->num_weapons)
931 victim->weaponstuck = 0;
934 victim->weaponactive = -1;
935 for (unsigned j = 0; j < Person::players.size(); j++) {
936 Person::players[j]->wentforweapon = 0;
939 animTarget = swordslashreversedanim;
940 animCurrent = swordslashreversedanim;
941 victim->animCurrent = swordslashreversalanim;
942 victim->animTarget = swordslashreversalanim;
944 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
945 if (victim->weaponactive != -1) {
946 victim->throwtogglekeydown = 1;
947 XYZ tempVelocity = victim->velocity * .2;
948 if (tempVelocity.x == 0)
950 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
951 victim->num_weapons--;
952 if (victim->num_weapons) {
953 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
954 if (victim->weaponstuck == victim->num_weapons)
955 victim->weaponstuck = 0;
958 victim->weaponactive = -1;
959 for (unsigned j = 0; j < Person::players.size(); j++) {
960 Person::players[j]->wentforweapon = 0;
963 animTarget = knifeslashreversedanim;
964 animCurrent = knifeslashreversedanim;
965 victim->animCurrent = knifeslashreversalanim;
966 victim->animTarget = knifeslashreversalanim;
968 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
969 victim->targettilt2 = targettilt2;
970 victim->frameCurrent = frameCurrent;
971 victim->frameTarget = frameTarget;
972 victim->target = target;
973 victim->velocity = 0;
974 victim->oldcoords = victim->coords;
975 victim->coords = coords;
976 victim->targetyaw = targetyaw;
977 victim->yaw = targetyaw;
978 victim->victim = this->shared_from_this();
980 if (animTarget == winduppunchanim) {
981 animTarget = winduppunchblockedanim;
982 victim->animTarget = blockhighleftanim;
983 victim->frameTarget = 1;
985 victim->victim = this->shared_from_this();
986 victim->targetyaw = targetyaw + 180;
988 if (animTarget == wolfslapanim) {
989 animTarget = winduppunchblockedanim;
990 victim->animTarget = blockhighleftanim;
991 victim->frameTarget = 1;
993 victim->victim = this->shared_from_this();
994 victim->targetyaw = targetyaw + 180;
996 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
997 animTarget = swordslashparriedanim;
998 parriedrecently = .4;
999 victim->parriedrecently = 0;
1000 victim->animTarget = swordslashparryanim;
1001 victim->frameTarget = 1;
1002 victim->target = .5;
1003 victim->victim = this->shared_from_this();
1004 victim->targetyaw = targetyaw + 180;
1006 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1007 if (victim->weaponactive != -1) {
1008 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1009 if (weapons[victim->weaponids[0]].getType() == staff)
1010 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1011 if (weapons[weaponids[0]].getType() == staff)
1012 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1013 emit_sound_at(swordstaffsound, victim->coords);
1015 emit_sound_at(metalhitsound, victim->coords);
1019 victim->Puff(righthand);
1021 victim->frameTarget = 0;
1022 victim->animTarget = staggerbackhighanim;
1023 victim->targetyaw = targetyaw + 180;
1025 aim = DoRotation(facing, 0, 90, 0) * 21;
1027 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1028 victim->num_weapons--;
1029 if (victim->num_weapons) {
1030 victim->weaponids[0] = victim->weaponids[num_weapons];
1031 if (victim->weaponstuck == victim->num_weapons)
1032 victim->weaponstuck = 0;
1034 victim->weaponactive = -1;
1035 for (unsigned i = 0; i < Person::players.size(); i++) {
1036 Person::players[i]->wentforweapon = 0;
1040 if (abs(Random() % 20) == 0) {
1041 if (weaponactive != -1) {
1042 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1043 if (weapons[victim->weaponids[0]].getType() == staff)
1044 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1045 if (weapons[weaponids[0]].getType() == staff)
1046 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1048 emit_sound_at(swordstaffsound, coords);
1050 emit_sound_at(metalhitsound, coords);
1058 animTarget = staggerbackhighanim;
1059 targetyaw = targetyaw + 180;
1061 aim = DoRotation(facing, 0, 90, 0) * 21;
1063 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1066 weaponids[0] = weaponids[num_weapons];
1067 if (weaponstuck == num_weapons)
1071 for (unsigned i = 0; i < Person::players.size(); i++) {
1072 Person::players[i]->wentforweapon = 0;
1079 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1080 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1081 victim->animTarget = dodgebackanim;
1082 victim->frameTarget = 0;
1086 rotatetarget = coords - victim->coords;
1087 Normalise(&rotatetarget);
1088 victim->targetyaw = -asin(0 - rotatetarget.x);
1089 victim->targetyaw *= 360 / 6.28;
1090 if (rotatetarget.z < 0)
1091 victim->targetyaw = 180 - victim->targetyaw;
1093 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1095 victim->lastattack3 = victim->lastattack2;
1096 victim->lastattack2 = victim->lastattack;
1097 victim->lastattack = victim->animTarget;
1099 victim->animTarget = sweepanim;
1100 victim->frameTarget = 0;
1104 rotatetarget = coords - victim->coords;
1105 Normalise(&rotatetarget);
1106 victim->targetyaw = -asin(0 - rotatetarget.x);
1107 victim->targetyaw *= 360 / 6.28;
1108 if (rotatetarget.z < 0)
1109 victim->targetyaw = 180 - victim->targetyaw;
1111 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1113 victim->lastattack3 = victim->lastattack2;
1114 victim->lastattack2 = victim->lastattack;
1115 victim->lastattack = victim->animTarget;
1120 victim->velocity = 0;
1122 if (aitype != playercontrolled)
1124 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1126 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1128 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1131 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1138 void Person::DoDamage(float howmuch)
1140 // subtract health (temporary?)
1141 if (tutoriallevel != 1)
1142 damage += howmuch / power;
1145 damagedealt += howmuch / power;
1147 damagetaken += howmuch / power;
1150 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1153 if (tutoriallevel != 1)
1154 permanentdamage += howmuch / 2 / power;
1155 if (tutoriallevel != 1)
1156 superpermanentdamage += howmuch / 4 / power;
1158 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1160 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1164 camerashake += howmuch / 100;
1165 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1166 blackout = damage / damagetolerance;
1171 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1172 aitype = attacktypecutoff;
1173 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1174 if (abs(Random() % 2) == 0) {
1175 aitype = gethelptype;
1178 aitype = attacktypecutoff;
1182 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1185 for (int i = 0; i < skeleton.num_joints; i++) {
1186 if (skeleton.free) {
1187 flatvelocity2 = skeleton.joints[i].velocity;
1188 flatfacing2 = skeleton.joints[i].position * scale + coords;
1190 flatvelocity2 = velocity;
1191 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1193 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1194 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1195 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1196 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1197 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1198 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1201 emit_sound_at(splattersound, coords);
1206 if (!dead && creature == wolftype) {
1207 award_bonus(0, Wolfbonus);
1214 if (tutoriallevel != 1 || id == 0)
1215 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1216 int whichsound = -1;
1218 if (creature == wolftype) {
1219 int i = abs(Random() % 2);
1221 whichsound = snarlsound;
1223 whichsound = snarl2sound;
1224 envsound[numenvsounds] = coords;
1225 envsoundvol[numenvsounds] = 16;
1226 envsoundlife[numenvsounds] = .4;
1229 if (creature == rabbittype) {
1230 int i = abs(Random() % 2);
1232 whichsound = rabbitpainsound;
1233 if (i == 1 && damage > damagetolerance)
1234 whichsound = rabbitpain1sound;
1235 envsound[numenvsounds] = coords;
1236 envsoundvol[numenvsounds] = 16;
1237 envsoundlife[numenvsounds] = .4;
1241 if (whichsound != -1) {
1242 emit_sound_at(whichsound, coords);
1249 * calculate/animate head facing direction?
1251 void Person::DoHead()
1253 static XYZ rotatearound;
1255 static float lookspeed = 500;
1257 if (!freeze && !winfreeze) {
1260 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1261 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1263 while (targetheadyaw > 180)targetheadyaw -= 360;
1264 while (targetheadyaw < -180)targetheadyaw += 360;
1266 if (targetheadyaw > 160)
1267 targetheadpitch = targetheadpitch * -1;
1268 if (targetheadyaw < -160)
1269 targetheadpitch = targetheadpitch * -1;
1270 if (targetheadyaw > 160)
1271 targetheadyaw = targetheadyaw - 180;
1272 if (targetheadyaw < -160)
1273 targetheadyaw = targetheadyaw + 180;
1275 if (targetheadpitch > 120)
1276 targetheadpitch = 120;
1277 if (targetheadpitch < -120)
1278 targetheadpitch = -120;
1279 if (targetheadyaw > 120)
1280 targetheadyaw = 120;
1281 if (targetheadyaw < -120)
1282 targetheadyaw = -120;
1285 targetheadpitch = 0;
1287 if (targetheadyaw > 80)
1289 if (targetheadyaw < -80)
1290 targetheadyaw = -80;
1291 if (targetheadpitch > 50)
1292 targetheadpitch = 50;
1293 if (targetheadpitch < -50)
1294 targetheadpitch = -50;
1297 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1298 headyaw = targetheadyaw;
1299 else if (headyaw > targetheadyaw) {
1300 headyaw -= multiplier * lookspeed;
1301 } else if (headyaw < targetheadyaw) {
1302 headyaw += multiplier * lookspeed;
1305 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1306 headpitch = targetheadpitch;
1307 else if (headpitch > targetheadpitch) {
1308 headpitch -= multiplier * lookspeed / 2;
1309 } else if (headpitch < targetheadpitch) {
1310 headpitch += multiplier * lookspeed / 2;
1313 rotatearound = jointPos(neck);
1314 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1318 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1319 facing = DoRotation(facing, headpitch * .4, 0, 0);
1320 facing = DoRotation(facing, 0, headyaw * .4, 0);
1323 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1324 facing = DoRotation(facing, headpitch * .8, 0, 0);
1325 facing = DoRotation(facing, 0, headyaw * .8, 0);
1328 if (animTarget == walkanim) {
1329 facing = DoRotation(facing, headpitch * .6, 0, 0);
1330 facing = DoRotation(facing, 0, headyaw * .6, 0);
1333 skeleton.specialforward[0] = facing;
1334 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1335 for (int i = 0; i < skeleton.num_muscles; i++) {
1336 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1337 skeleton.FindRotationMuscle(i, animTarget);
1344 * ragdolls character?
1346 void Person::RagDoll(bool checkcollision)
1351 if (!skeleton.free) {
1354 if (id == 0 && isFlip())
1361 facing = DoRotation(facing, 0, yaw, 0);
1363 skeleton.freetime = 0;
1365 skeleton.longdead = 0;
1368 skeleton.broken = 0;
1369 skeleton.spinny = 1;
1371 skeleton.freefall = 1;
1373 if (!isnormal(velocity.x)) velocity.x = 0;
1374 if (!isnormal(velocity.y)) velocity.y = 0;
1375 if (!isnormal(velocity.z)) velocity.z = 0;
1376 if (!isnormal(yaw)) yaw = 0;
1377 if (!isnormal(coords.x)) coords = 0;
1378 if (!isnormal(tilt)) tilt = 0;
1379 if (!isnormal(tilt2)) tilt2 = 0;
1381 for (int i = 0; i < skeleton.num_joints; i++) {
1382 skeleton.joints[i].delay = 0;
1383 skeleton.joints[i].locked = 0;
1384 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1385 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1386 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1387 skeleton.joints[i].position.y += .1;
1388 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1389 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1392 for (int i = 0; i < skeleton.num_joints; i++) {
1393 skeleton.joints[i].velocity = 0;
1394 skeleton.joints[i].velchange = 0;
1396 skeleton.DoConstraints(&coords, &scale);
1397 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1398 skeleton.DoConstraints(&coords, &scale);
1399 skeleton.DoConstraints(&coords, &scale);
1400 skeleton.DoConstraints(&coords, &scale);
1401 skeleton.DoConstraints(&coords, &scale);
1404 speed = animation[animTarget].speed[frameTarget] * 2;
1405 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1406 speed = animation[animCurrent].speed[frameCurrent] * 2;
1409 speed = transspeed * 2;
1413 for (int i = 0; i < skeleton.num_joints; i++) {
1414 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1415 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);
1417 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1418 change.x = (float)(Random() % 100) / 100;
1419 change.y = (float)(Random() % 100) / 100;
1420 change.z = (float)(Random() % 100) / 100;
1421 skeleton.joints[i].velocity += change;
1422 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1424 change.x = (float)(Random() % 100) / 100;
1425 change.y = (float)(Random() % 100) / 100;
1426 change.z = (float)(Random() % 100) / 100;
1427 skeleton.joints[i].velchange += change;
1428 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1431 if (checkcollision) {
1438 for (j = 0; j < skeleton.num_joints; j++) {
1439 average += skeleton.joints[j].position;
1443 coords += average * scale;
1444 for (j = 0; j < skeleton.num_joints; j++) {
1445 skeleton.joints[j].position -= average;
1448 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1449 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1450 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1451 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1452 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1455 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1456 coords.x = lowpoint.x;
1457 coords.z = lowpoint.z;
1466 for (int i = 0; i < skeleton.num_joints; i++) {
1467 velocity += skeleton.joints[i].velocity * scale;
1469 velocity /= skeleton.num_joints;
1472 if (Random() % 2 == 0) {
1473 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1474 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1475 weapons[weaponids[0]].velocity.x += .01;
1478 weaponids[0] = weaponids[num_weapons];
1479 if (weaponstuck == num_weapons)
1483 for (unsigned i = 0; i < Person::players.size(); i++) {
1484 Person::players[i]->wentforweapon = 0;
1489 animTarget = bounceidleanim;
1490 animCurrent = bounceidleanim;
1500 void Person::FootLand(int which, float opacity)
1502 static XYZ terrainlight;
1503 static XYZ footvel, footpoint;
1504 if (opacity >= 1 || skiddelay <= 0)
1508 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1510 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1511 //footpoint.y=coords.y;
1512 if (distsq(&footpoint, &viewer))
1513 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1514 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1515 footvel = velocity / 5;
1519 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1521 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1522 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1523 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1524 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1525 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1526 if (opacity >= 1 || detail == 2)
1528 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1529 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1530 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1531 footvel = velocity / 5;
1535 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1537 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1538 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1539 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1540 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1541 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1542 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1543 footvel = velocity / 5;
1547 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1549 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1550 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1551 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1552 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1553 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1554 if (opacity >= 1 || detail == 2)
1556 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1557 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1558 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1559 footvel = velocity / 5;
1563 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1565 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1566 //footpoint.y=coords.y;
1567 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1568 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1573 * make a puff effect at a body part (dust effect?)
1575 void Person::Puff(int whichlabel)
1577 static XYZ footvel, footpoint;
1580 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1581 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1585 * I think I added this in an attempt to clean up code
1587 void Person::setAnimation(int animation)
1589 animTarget = animation;
1598 void Person::DoAnimations()
1600 if (!skeleton.free) {
1601 static float oldtarget;
1603 if (isIdle() && animCurrent != getIdle())
1604 normalsupdatedelay = 0;
1606 if (animTarget == tempanim || animCurrent == tempanim) {
1607 animation[tempanim] = tempanimation;
1609 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1615 vel[0] = velocity.x;
1616 vel[1] = velocity.y;
1617 vel[2] = velocity.z;
1620 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1621 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1623 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1625 if (!crouchkeydown && velocity.y >= -15)
1628 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1633 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1635 if (normaldotproduct(targfacing, velocity) >= -.3)
1636 animTarget = flipanim;
1638 animTarget = backflipanim;
1639 crouchtogglekeydown = 1;
1647 if (animation[animTarget].attack != reversed)
1649 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1650 crouchtogglekeydown = 0;
1651 if (aitype == playercontrolled)
1654 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1657 crouchtogglekeydown = 1;
1661 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1663 normalsupdatedelay = 0;
1667 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1669 emit_sound_at(fireendsound, coords);
1670 pause_sound(stream_firesound);
1674 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1675 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1677 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1678 if (normaldotproduct(victim->facing, facing) > 0)
1679 victim->animTarget = rabbittackledbackanim;
1681 victim->animTarget = rabbittackledfrontanim;
1682 victim->frameTarget = 2;
1685 victim->targetyaw = yaw;
1686 if (victim->aitype == gethelptype)
1687 victim->DoDamage(victim->damagetolerance - victim->damage);
1688 //victim->DoDamage(30);
1689 if (creature == wolftype) {
1691 emit_sound_at(clawslicesound, victim->coords);
1693 victim->DoBloodBig(1 / victim->armorhead, 210);
1695 award_bonus(id, TackleBonus,
1696 victim->aitype == gethelptype ? 50 : 0);
1700 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1701 if (weapons[weaponids[0]].getType() == knife) {
1702 if (weaponactive == -1)
1704 else if (weaponactive == 0)
1707 if (weaponactive == -1) {
1708 emit_sound_at(knifesheathesound, coords);
1710 if (weaponactive != -1) {
1711 emit_sound_at(knifedrawsound, coords, 128);
1714 drawtogglekeydown = 1;
1717 if (tutoriallevel != 1 || id == 0)
1718 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1721 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1722 if (animation[animTarget].label[frameTarget] == 1)
1723 whichsound = footstepsound;
1725 whichsound = footstepsound2;
1726 if (animation[animTarget].label[frameTarget] == 1)
1728 if (animation[animTarget].label[frameTarget] == 2)
1730 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1736 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1737 if (animation[animTarget].label[frameTarget] == 1)
1738 whichsound = footstepsound3;
1740 whichsound = footstepsound4;
1744 if (animation[animTarget].label[frameTarget] == 1)
1745 whichsound = footstepsound3;
1747 whichsound = footstepsound4;
1749 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1750 if (animation[animTarget].attack != neutral) {
1751 unsigned r = abs(Random() % 3);
1753 whichsound = lowwhooshsound;
1755 whichsound = midwhooshsound;
1757 whichsound = highwhooshsound;
1759 if (animation[animTarget].attack == neutral)
1760 whichsound = movewhooshsound;
1761 } else if (animation[animTarget].label[frameTarget] == 4)
1762 whichsound = knifeswishsound;
1763 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1764 whichsound = landsound2;
1766 emit_sound_at(whichsound, coords, 256.);
1769 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1770 envsound[numenvsounds] = coords;
1771 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1772 envsoundvol[numenvsounds] = 15;
1774 envsoundvol[numenvsounds] = 6;
1775 envsoundlife[numenvsounds] = .4;
1779 if (animation[animTarget].label[frameTarget] == 3) {
1781 emit_sound_at(whichsound, coords, 128.);
1786 if (tutoriallevel != 1 || id == 0)
1787 if (speechdelay <= 0)
1788 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1789 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1790 int whichsound = -1;
1791 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1792 if (animation[animTarget].attack != neutral) {
1793 unsigned r = abs(Random() % 4);
1794 if (creature == rabbittype) {
1795 if (r == 0) whichsound = rabbitattacksound;
1796 if (r == 1) whichsound = rabbitattack2sound;
1797 if (r == 2) whichsound = rabbitattack3sound;
1798 if (r == 3) whichsound = rabbitattack4sound;
1800 if (creature == wolftype) {
1801 if (r == 0) whichsound = barksound;
1802 if (r == 1) whichsound = bark2sound;
1803 if (r == 2) whichsound = bark3sound;
1804 if (r == 3) whichsound = barkgrowlsound;
1810 if (whichsound != -1) {
1811 emit_sound_at(whichsound, coords);
1817 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
1823 currentoffset = targetoffset;
1824 frameTarget = frameCurrent;
1825 animCurrent = animTarget;
1828 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1829 for (unsigned i = 0; i < weapons.size(); i++) {
1830 if (weapons[i].owner == -1)
1831 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
1832 if (distsq(&coords, &weapons[i].position) >= 1) {
1833 if (weapons[i].getType() != staff) {
1834 emit_sound_at(knifedrawsound, coords, 128.);
1843 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1844 for (unsigned i = 0; i < weapons.size(); i++) {
1845 bool willwork = true;
1846 if (weapons[i].owner != -1)
1847 if (Person::players[weapons[i].owner]->weaponstuck != -1)
1848 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
1849 if (Person::players[weapons[i].owner]->num_weapons > 1)
1851 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
1852 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
1853 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
1854 bool fleshstuck = false;
1855 if (weapons[i].owner != -1)
1856 if (victim->weaponstuck != -1) {
1857 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1862 emit_sound_at(fleshstabremovesound, coords, 128.);
1864 if (weapons[i].getType() != staff) {
1865 emit_sound_at(knifedrawsound, coords, 128.);
1868 if (weapons[i].owner != -1) {
1869 victim = Person::players[weapons[i].owner];
1870 if (victim->num_weapons == 1)
1871 victim->num_weapons = 0;
1873 victim->num_weapons = 1;
1875 //victim->weaponactive=-1;
1876 victim->skeleton.longdead = 0;
1877 victim->skeleton.free = 1;
1878 victim->skeleton.broken = 0;
1880 for (int j = 0; j < victim->skeleton.num_joints; j++) {
1881 victim->skeleton.joints[j].velchange = 0;
1882 victim->skeleton.joints[j].locked = 0;
1888 Normalise(&relative);
1889 XYZ footvel, footpoint;
1891 footpoint = weapons[i].position;
1892 if (victim->weaponstuck != -1) {
1893 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1895 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
1896 weapons[i].bloody = 2;
1897 weapons[i].blooddrip = 5;
1898 victim->weaponstuck = -1;
1901 if (victim->num_weapons > 0) {
1902 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
1903 victim->weaponstuck = 0;
1904 if (victim->weaponids[0] == int(i))
1905 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1908 victim->jointVel(abdomen) += relative * 6;
1909 victim->jointVel(neck) += relative * 6;
1910 victim->jointVel(rightshoulder) += relative * 6;
1911 victim->jointVel(leftshoulder) += relative * 6;
1919 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
1920 if (weaponactive == -1)
1922 else if (weaponactive == 0) {
1924 if (num_weapons == 2) {
1926 buffer = weaponids[0];
1927 weaponids[0] = weaponids[1];
1928 weaponids[1] = buffer;
1931 if (weaponactive == -1) {
1932 emit_sound_at(knifesheathesound, coords, 128.);
1934 if (weaponactive != -1) {
1935 emit_sound_at(knifedrawsound, coords, 128.);
1940 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
1941 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
1942 Normalise(&rotatetarget);
1943 targetyaw = -asin(0 - rotatetarget.x);
1944 targetyaw *= 360 / 6.28;
1945 if (rotatetarget.z < 0)
1946 targetyaw = 180 - targetyaw;
1948 if (animTarget == walljumprightkickanim)
1950 if (animTarget == walljumpleftkickanim)
1956 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
1959 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
1964 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
1965 animTarget = rabbittackleanim;
1967 emit_sound_at(jumpsound, coords);
1975 targetloc = velocity;
1976 Normalise(&targetloc);
1977 targetloc += coords;
1978 for (unsigned i = 0; i < Person::players.size(); i++) {
1980 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
1981 closestdist = distsq(&targetloc, &Person::players[i]->coords);
1985 if (closestid != -1)
1986 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
1988 victim = Person::players[closestid];
1989 coords = victim->coords;
1990 animCurrent = rabbittacklinganim;
1991 animTarget = rabbittacklinganim;
1995 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
1996 rotatetarget = coords - victim->coords;
1997 Normalise(&rotatetarget);
1998 targetyaw = -asin(0 - rotatetarget.x);
1999 targetyaw *= 360 / 6.28;
2000 if (rotatetarget.z < 0)
2001 targetyaw = 180 - targetyaw;
2003 if (animTarget != rabbitrunninganim) {
2004 emit_sound_at(jumpsound, coords, 128.);
2010 float damagemult = 1 * power;
2011 if (creature == wolftype)
2012 damagemult = 2.5 * power;
2014 damagemult /= victim->damagetolerance / 200;
2016 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2017 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2018 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2022 if (Random() % 2 || creature == wolftype) {
2025 if (creature == wolftype)
2028 if (tutoriallevel != 1) {
2029 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2031 if (creature == wolftype) {
2032 emit_sound_at(clawslicesound, victim->coords, 128.);
2034 victim->DoBloodBig(2 / victim->armorhead, 175);
2038 relative = victim->coords - coords;
2040 Normalise(&relative);
2041 relative = DoRotation(relative, 0, -90, 0);
2042 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2043 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2045 victim->jointVel(head) += relative * damagemult * 200;
2048 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2054 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2055 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2059 if (Random() % 2 || creature == wolftype) {
2061 if (creature == wolftype)
2064 emit_sound_at(whooshhitsound, victim->coords);
2065 if (creature == wolftype) {
2066 emit_sound_at(clawslicesound, victim->coords, 128.);
2068 victim->DoBloodBig(2, 175);
2072 relative = victim->coords - coords;
2074 Normalise(&relative);
2076 Normalise(&relative);
2077 relative = DoRotation(relative, 0, 90, 0);
2078 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2079 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2081 victim->jointVel(head) += relative * damagemult * 100;
2084 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2088 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2089 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2095 if (tutoriallevel != 1) {
2096 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2098 if (creature == wolftype) {
2099 emit_sound_at(clawslicesound, victim->coords, 128.);
2101 victim->DoBloodBig(2 / victim->armorhead, 175);
2107 Normalise(&relative);
2108 relative = DoRotation(relative, 0, -90, 0);
2109 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2110 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2112 victim->jointVel(head) += relative * damagemult * 200;
2115 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2117 if (victim->damage > victim->damagetolerance)
2118 award_bonus(id, style);
2124 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2125 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2131 if (tutoriallevel != 1) {
2132 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2134 if (creature == wolftype) {
2135 emit_sound_at(clawslicesound, victim->coords, 128.);
2137 victim->DoBloodBig(2 / victim->armorhead, 175);
2143 Normalise(&relative);
2144 relative = DoRotation(relative, 0, 90, 0);
2145 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2146 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2148 victim->jointVel(head) += relative * damagemult * 200;
2151 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2153 if (victim->damage > victim->damagetolerance)
2154 award_bonus(id, style);
2160 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2161 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2169 emit_sound_at(whooshhitsound, victim->coords);
2172 relative = victim->coords - coords;
2174 Normalise(&relative);
2175 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2176 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2178 victim->jointVel(head) += relative * damagemult * 100;
2181 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2185 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2186 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2190 emit_sound_at(whooshhitsound, victim->coords, 128.);
2192 victim->skeleton.longdead = 0;
2193 victim->skeleton.free = 1;
2194 victim->skeleton.broken = 0;
2195 victim->skeleton.spinny = 1;
2197 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2198 victim->skeleton.joints[i].velchange = 0;
2199 victim->skeleton.joints[i].delay = 0;
2200 victim->skeleton.joints[i].locked = 0;
2201 //victim->skeleton.joints[i].velocity=0;
2207 Normalise(&relative);
2208 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2209 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2210 victim->skeleton.joints[i].position.y += relative.y * .3;
2211 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2212 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2214 victim->Puff(abdomen);
2215 victim->jointVel(abdomen).y = relative.y * 400;
2219 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2220 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2224 if (tutoriallevel != 1) {
2225 emit_sound_at(heavyimpactsound, coords, 128.);
2228 relative = victim->coords - coords;
2230 Normalise(&relative);
2231 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2232 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2234 victim->Puff(abdomen);
2235 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2239 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2240 victim->jointVel(abdomen) += relative * damagemult * 300;
2244 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2245 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2249 if (tutoriallevel != 1) {
2250 emit_sound_at(thudsound, coords);
2253 victim->skeleton.longdead = 0;
2254 victim->skeleton.free = 1;
2255 victim->skeleton.broken = 0;
2256 victim->skeleton.spinny = 1;
2258 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2259 victim->skeleton.joints[i].velchange = 0;
2260 //victim->skeleton.joints[i].delay=0;
2261 victim->skeleton.joints[i].locked = 0;
2264 relative = victim->coords - coords;
2265 Normalise(&relative);
2267 Normalise(&relative);
2268 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2269 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2274 victim->Puff(abdomen);
2275 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2276 victim->jointVel(abdomen) += relative * damagemult * 200;
2285 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2288 if (!victim->skeleton.free)
2292 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2293 emit_sound_at(knifesheathesound, coords, 128.);
2296 if (victim && hasvictim) {
2297 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2299 XYZ where, startpoint, endpoint, movepoint, colpoint;
2300 float rotationpoint;
2302 if (weapons[weaponids[weaponactive]].getType() == knife) {
2303 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2304 where -= victim->coords;
2305 if (!victim->skeleton.free)
2306 where = DoRotation(where, 0, -victim->yaw, 0);
2309 startpoint.y += 100;
2313 if (weapons[weaponids[weaponactive]].getType() == sword) {
2314 where = weapons[weaponids[weaponactive]].position;
2315 where -= victim->coords;
2316 if (!victim->skeleton.free)
2317 where = DoRotation(where, 0, -victim->yaw, 0);
2319 where = weapons[weaponids[weaponactive]].tippoint;
2320 where -= victim->coords;
2321 if (!victim->skeleton.free)
2322 where = DoRotation(where, 0, -victim->yaw, 0);
2325 if (weapons[weaponids[weaponactive]].getType() == staff) {
2326 where = weapons[weaponids[weaponactive]].position;
2327 where -= victim->coords;
2328 if (!victim->skeleton.free)
2329 where = DoRotation(where, 0, -victim->yaw, 0);
2331 where = weapons[weaponids[weaponactive]].tippoint;
2332 where -= victim->coords;
2333 if (!victim->skeleton.free)
2334 where = DoRotation(where, 0, -victim->yaw, 0);
2339 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2341 if (whichtri != -1) {
2342 if (victim->dead != 2) {
2343 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2345 award_bonus(id, FinishedBonus);
2348 weapons[weaponids[weaponactive]].bloody = 2;
2350 victim->skeleton.longdead = 0;
2351 victim->skeleton.free = 1;
2352 victim->skeleton.broken = 0;
2354 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2355 victim->skeleton.joints[i].velchange = 0;
2356 victim->skeleton.joints[i].locked = 0;
2357 //victim->skeleton.joints[i].velocity=0;
2359 emit_sound_at(fleshstabsound, coords, 128);
2362 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2363 weapons[weaponids[weaponactive]].blooddrip += 5;
2364 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2366 if (whichtri == -1) {
2368 emit_sound_at(knifesheathesound, coords, 128.);
2374 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2376 emit_sound_at(knifedrawsound, coords, 128);
2379 if (victim && hasvictim) {
2380 XYZ footvel, footpoint;
2382 emit_sound_at(fleshstabremovesound, coords, 128.);
2385 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2387 if (weapons[weaponids[weaponactive]].getType() == sword) {
2388 XYZ where, startpoint, endpoint, movepoint;
2389 float rotationpoint;
2392 where = weapons[weaponids[weaponactive]].position;
2393 where -= victim->coords;
2394 if (!victim->skeleton.free)
2395 where = DoRotation(where, 0, -victim->yaw, 0);
2397 where = weapons[weaponids[weaponactive]].tippoint;
2398 where -= victim->coords;
2399 if (!victim->skeleton.free)
2400 where = DoRotation(where, 0, -victim->yaw, 0);
2405 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2406 footpoint += victim->coords;
2408 if (whichtri == -1) {
2409 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2412 if (weapons[weaponids[weaponactive]].getType() == staff) {
2413 XYZ where, startpoint, endpoint, movepoint;
2414 float rotationpoint;
2417 where = weapons[weaponids[weaponactive]].position;
2418 where -= victim->coords;
2419 if (!victim->skeleton.free)
2420 where = DoRotation(where, 0, -victim->yaw, 0);
2422 where = weapons[weaponids[weaponactive]].tippoint;
2423 where -= victim->coords;
2424 if (!victim->skeleton.free)
2425 where = DoRotation(where, 0, -victim->yaw, 0);
2430 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2431 footpoint += victim->coords;
2433 if (whichtri == -1) {
2434 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2437 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2439 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2440 victim->skeleton.longdead = 0;
2441 victim->skeleton.free = 1;
2442 victim->skeleton.broken = 0;
2444 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2445 victim->skeleton.joints[i].velchange = 0;
2446 victim->skeleton.joints[i].locked = 0;
2447 //victim->skeleton.joints[i].velocity=0;
2453 Normalise(&relative);
2454 //victim->Puff(abdomen);
2456 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2458 if (victim->bloodloss < victim->damagetolerance) {
2459 victim->bloodloss += 1000;
2463 victim->jointVel(abdomen) += relative * damagemult * 20;
2467 if (!hasvictim && onterrain) {
2468 weapons[weaponids[weaponactive]].bloody = 0;
2469 weapons[weaponids[weaponactive]].blooddrip = 0;
2473 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2474 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2482 if (tutoriallevel != 1) {
2483 emit_sound_at(heavyimpactsound, victim->coords, 128);
2488 relative = victim->coords - coords;
2490 Normalise(&relative);
2491 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2492 victim->skeleton.joints[i].velocity = relative * 30;
2494 victim->jointVel(head) += relative * damagemult * 150;
2496 victim->frameTarget = 0;
2497 victim->animTarget = staggerbackhardanim;
2498 victim->targetyaw = targetyaw + 180;
2500 victim->stunned = 1;
2503 victim->Puff(abdomen);
2504 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2511 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2512 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2516 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2517 if (tutoriallevel != 1) {
2518 emit_sound_at(thudsound, victim->coords);
2520 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2521 if (tutoriallevel != 1) {
2522 emit_sound_at(whooshhitsound, victim->coords);
2525 if (tutoriallevel != 1) {
2526 emit_sound_at(heavyimpactsound, victim->coords);
2530 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2533 relative = victim->coords - coords;
2535 Normalise(&relative);
2537 Normalise(&relative);
2538 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2539 victim->skeleton.joints[i].velocity = relative * 5;
2541 victim->jointVel(abdomen) += relative * damagemult * 400;
2543 victim->frameTarget = 0;
2544 victim->animTarget = staggerbackhardanim;
2545 victim->targetyaw = targetyaw + 180;
2547 victim->stunned = 1;
2549 victim->Puff(abdomen);
2550 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2556 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2557 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2558 if (victim->id == 0)
2560 emit_sound_at(landsound2, victim->coords);
2566 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2567 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2568 if (victim->id == 0)
2571 if (weaponactive != -1) {
2572 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2573 if (weapons[victim->weaponids[0]].getType() == staff)
2574 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2575 if (weapons[weaponids[0]].getType() == staff)
2576 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2578 emit_sound_at(swordstaffsound, victim->coords);
2580 emit_sound_at(metalhitsound, victim->coords);
2588 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2589 if (weaponactive != -1) {
2592 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);
2594 weapons[weaponids[0]].thrown(aim * 50);
2597 weaponids[0] = weaponids[num_weapons];
2603 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2605 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2607 if (tutoriallevel != 1)
2608 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2610 award_bonus(id, Slicebonus);
2611 if (tutoriallevel != 1) {
2612 emit_sound_at(knifeslicesound, victim->coords);
2614 //victim->jointVel(abdomen)+=relative*damagemult*200;
2615 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2616 if (victim->id != 0 || difficulty == 2) {
2617 victim->frameTarget = 0;
2618 victim->animTarget = staggerbackhardanim;
2619 victim->targetyaw = targetyaw + 180;
2623 victim->lowreversaldelay = 0;
2624 victim->highreversaldelay = 0;
2625 if (aitype != playercontrolled)
2626 weaponmissdelay = .6;
2628 if (tutoriallevel != 1)
2629 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2630 weapons[weaponids[weaponactive]].bloody = 1;
2631 if (tutoriallevel != 1)
2632 weapons[weaponids[weaponactive]].blooddrip += 3;
2634 XYZ footvel, footpoint;
2636 if (skeleton.free) {
2637 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2639 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2641 if (tutoriallevel != 1) {
2643 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2644 footvel = DoRotation(facing, 0, 90, 0) * .8;
2646 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2647 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2648 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2649 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2651 if (tutoriallevel == 1) {
2652 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2654 victim->DoDamage(damagemult * 0);
2657 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2658 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2659 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2660 award_bonus(id, Slashbonus);
2662 if (tutoriallevel != 1) {
2663 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2664 victim->DoBloodBig(2 / victim->armorhigh, 190);
2666 victim->DoBloodBig(2 / victim->armorhigh, 185);
2667 victim->deathbleeding = 1;
2668 emit_sound_at(swordslicesound, victim->coords);
2670 //victim->jointVel(abdomen)+=relative*damagemult*200;
2671 if (tutoriallevel != 1) {
2672 victim->frameTarget = 0;
2673 victim->animTarget = staggerbackhardanim;
2674 victim->targetyaw = targetyaw + 180;
2678 if (tutoriallevel != 1) {
2679 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2680 weapons[weaponids[weaponactive]].bloody = 1;
2681 weapons[weaponids[weaponactive]].blooddrip += 3;
2683 float bloodlossamount;
2684 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2685 victim->bloodloss += bloodlossamount / victim->armorhigh;
2686 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2687 victim->DoDamage(damagemult * 0);
2689 XYZ footvel, footpoint;
2691 if (skeleton.free) {
2692 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2694 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2697 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2698 footvel = DoRotation(facing, 0, 90, 0) * .8;
2700 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2701 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2702 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2703 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2706 if (victim->weaponactive != -1) {
2707 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2708 if (weapons[victim->weaponids[0]].getType() == staff)
2709 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2710 if (weapons[weaponids[0]].getType() == staff)
2711 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2713 emit_sound_at(swordstaffsound, victim->coords);
2715 emit_sound_at(metalhitsound, victim->coords);
2721 victim->Puff(righthand);
2723 victim->frameTarget = 0;
2724 victim->animTarget = staggerbackhighanim;
2725 victim->targetyaw = targetyaw + 180;
2727 aim = DoRotation(facing, 0, 90, 0) * 21;
2729 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2730 victim->num_weapons--;
2731 if (victim->num_weapons) {
2732 victim->weaponids[0] = victim->weaponids[num_weapons];
2733 if (victim->weaponstuck == victim->num_weapons)
2734 victim->weaponstuck = 0;
2736 victim->weaponactive = -1;
2737 for (unsigned i = 0; i < Person::players.size(); i++) {
2738 Person::players[i]->wentforweapon = 0;
2745 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2746 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2747 if (tutoriallevel != 1) {
2748 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2752 if (Random() % 2 || creature == wolftype) {
2755 emit_sound_at(staffheadsound, victim->coords);
2759 relative = victim->coords - coords;
2761 Normalise(&relative);
2762 relative = DoRotation(relative, 0, 90, 0);
2764 Normalise(&relative);
2765 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2766 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2768 victim->jointVel(head) += relative * damagemult * 230;
2769 victim->jointVel(neck) += relative * damagemult * 230;
2772 if (tutoriallevel != 1) {
2773 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2775 award_bonus(id, solidhit, 30);
2780 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2781 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2782 if (tutoriallevel != 1) {
2783 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2787 if (Random() % 2 || creature == wolftype) {
2790 emit_sound_at(staffheadsound, victim->coords);
2794 relative = victim->coords - coords;
2796 Normalise(&relative);
2797 relative = DoRotation(relative, 0, -90, 0);
2798 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2799 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2801 victim->jointVel(head) += relative * damagemult * 220;
2802 victim->jointVel(neck) += relative * damagemult * 220;
2805 if (tutoriallevel != 1) {
2806 victim->DoDamage(damagemult * 350 / victim->protectionhead);
2808 award_bonus(id, solidhit, 60);
2813 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
2814 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
2816 if (tutoriallevel != 1) {
2818 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
2821 if (Random() % 2 || creature == wolftype) {
2824 emit_sound_at(staffbodysound, victim->coords);
2826 victim->skeleton.longdead = 0;
2827 victim->skeleton.free = 1;
2828 victim->skeleton.broken = 0;
2830 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2831 victim->skeleton.joints[i].velchange = 0;
2832 victim->skeleton.joints[i].locked = 0;
2833 //victim->skeleton.joints[i].velocity=0;
2839 /*relative=victim->coords-coords;
2841 Normalise(&relative);
2842 relative=DoRotation(relative,0,90,0);*/
2844 Normalise(&relative);
2845 if (!victim->dead) {
2846 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2847 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
2850 victim->jointVel(abdomen) += relative * damagemult * 40;
2853 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2854 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
2857 //victim->jointVel(abdomen)+=relative*damagemult*20;
2859 victim->Puff(abdomen);
2860 if (tutoriallevel != 1) {
2861 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
2863 if (!victim->dead) {
2864 award_bonus(id, solidhit, 40);
2870 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
2871 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
2876 relative = victim->coords - coords;
2878 Normalise(&relative);
2882 if (animation[victim->animTarget].height == lowheight) {
2888 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2889 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2891 victim->jointVel(head) += relative * damagemult * 200;
2892 if (tutoriallevel != 1) {
2893 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2896 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2897 if (victim->howactive == typesleeping)
2898 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2899 if (creature == wolftype) {
2900 emit_sound_at(clawslicesound, victim->coords, 128.);
2902 victim->DoBloodBig(2 / victim->armorhead, 175);
2905 if (victim->damage >= victim->damagetolerance)
2907 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2908 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
2910 victim->jointVel(abdomen) += relative * damagemult * 200;
2911 victim->frameTarget = 0;
2912 victim->animTarget = staggerbackhighanim;
2913 victim->targetyaw = targetyaw + 180;
2915 if (tutoriallevel != 1) {
2916 emit_sound_at(landsound2, victim->coords, 128.);
2918 victim->Puff(abdomen);
2919 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
2920 if (creature == wolftype) {
2921 emit_sound_at(clawslicesound, victim->coords, 128.);
2923 victim->DoBloodBig(2 / victim->armorhigh, 170);
2930 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
2931 if ((victim->animTarget != jumpupanim) &&
2932 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
2933 (victim != this->shared_from_this())) {
2937 if (tutoriallevel != 1) {
2938 emit_sound_at(landsound2, victim->coords, 128.);
2941 relative = victim->coords - coords;
2943 Normalise(&relative);
2945 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
2948 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2949 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
2951 relative = DoRotation(relative, 0, -90, 0);
2953 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2954 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)
2955 victim->skeleton.joints[i].velocity = relative * 80;
2957 victim->Puff(rightankle);
2958 victim->Puff(leftankle);
2959 victim->DoDamage(damagemult * 40 / victim->protectionlow);
2961 if (victim->damage >= victim->damagetolerance)
2963 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2964 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
2966 relative = DoRotation(relative, 0, -90, 0);
2967 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2968 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)
2969 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
2971 victim->jointVel(abdomen) += relative * damagemult * 200;
2972 victim->frameTarget = 0;
2973 victim->animTarget = staggerbackhighanim;
2974 victim->targetyaw = targetyaw + 180;
2976 if (tutoriallevel != 1) {
2977 emit_sound_at(landsound2, victim->coords, 128.);
2979 victim->Puff(abdomen);
2980 victim->DoDamage(damagemult * 30 / victim->protectionlow);
2988 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
2989 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
2997 if (tutoriallevel != 1) {
2998 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3000 if (creature == wolftype) {
3001 emit_sound_at(clawslicesound, victim->coords, 128);
3003 victim->DoBloodBig(2 / victim->armorhigh, 170);
3007 relative = victim->coords - oldcoords;
3009 Normalise(&relative);
3010 //relative=DoRotation(relative,0,-90,0);
3011 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3012 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3014 victim->jointVel(abdomen) += relative * damagemult * 200;
3016 victim->Puff(abdomen);
3017 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3019 award_bonus(id, Reversal);
3022 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3023 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3024 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3025 takeWeapon(victim->weaponids[victim->weaponactive]);
3026 victim->num_weapons--;
3027 if (victim->num_weapons > 0) {
3028 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3030 victim->weaponactive = -1;
3035 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3043 emit_sound_at(whooshhitsound, victim->coords, 128.);
3046 relative = victim->coords - oldcoords;
3048 Normalise(&relative);
3049 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3050 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3052 victim->jointVel(abdomen) += relative * damagemult * 200;
3054 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3057 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3066 award_bonus(id, staffreversebonus);
3068 if (tutoriallevel != 1) {
3069 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3072 award_bonus(id, staffreversebonus); // Huh, again?
3075 relative = victim->coords - oldcoords;
3077 Normalise(&relative);
3078 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3079 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3081 victim->jointVel(abdomen) += relative * damagemult * 200;
3083 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3086 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3092 Normalise(&relative);
3094 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3095 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3097 victim->jointVel(lefthand) *= .1;
3098 victim->jointVel(leftwrist) *= .2;
3099 victim->jointVel(leftelbow) *= .5;
3100 victim->jointVel(leftshoulder) *= .7;
3101 victim->jointVel(righthand) *= .1;
3102 victim->jointVel(rightwrist) *= .2;
3103 victim->jointVel(rightelbow) *= .5;
3104 victim->jointVel(rightshoulder) *= .7;
3106 victim->Puff(abdomen);
3107 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3109 award_bonus(id, Reversal);
3113 if (weaponactive != -1 || creature == wolftype)
3115 if (creature == rabbittype && weaponactive != -1)
3116 if (weapons[weaponids[0]].getType() == staff)
3119 if (weaponactive != -1) {
3120 victim->DoBloodBig(2 / victim->armorhigh, 225);
3121 emit_sound_at(knifeslicesound, victim->coords);
3122 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3123 weapons[weaponids[weaponactive]].bloody = 1;
3124 weapons[weaponids[weaponactive]].blooddrip += 3;
3126 if (weaponactive == -1 && creature == wolftype) {
3128 emit_sound_at(clawslicesound, victim->coords, 128.);
3130 victim->DoBloodBig(2 / victim->armorhigh, 175);
3137 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3143 Normalise(&relative);
3145 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3146 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3148 victim->jointVel(lefthand) *= .1 - 1;
3149 victim->jointVel(leftwrist) *= .2 - 1;
3150 victim->jointVel(leftelbow) *= .5 - 1;
3151 victim->jointVel(leftshoulder) *= .7 - 1;
3152 victim->jointVel(righthand) *= .1 - 1;
3153 victim->jointVel(rightwrist) *= .2 - 1;
3154 victim->jointVel(rightelbow) *= .5 - 1;
3155 victim->jointVel(rightshoulder) *= .7 - 1;
3157 award_bonus(id, swordreversebonus);
3160 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3168 if (tutoriallevel != 1) {
3169 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3173 relative = victim->coords - oldcoords;
3175 Normalise(&relative);
3176 relative = DoRotation(relative, 0, -90, 0);
3177 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3178 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3180 victim->jointVel(abdomen) += relative * damagemult * 200;
3181 victim->Puff(abdomen);
3182 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3184 award_bonus(id, Reversal);
3187 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3190 victim->skeleton.spinny = 0;
3192 relative = facing * -1;
3194 Normalise(&relative);
3195 if (victim->id == 0)
3197 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3198 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3200 victim->damage = victim->damagetolerance;
3201 victim->permanentdamage = victim->damagetolerance - 1;
3204 if (weaponactive != -1 || creature == wolftype)
3206 if (creature == rabbittype && weaponactive != -1)
3207 if (weapons[weaponids[0]].getType() == staff)
3210 if (weaponactive != -1) {
3211 victim->DoBloodBig(200, 225);
3212 emit_sound_at(knifeslicesound, victim->coords);
3214 weapons[weaponids[weaponactive]].bloody = 2;
3215 weapons[weaponids[weaponactive]].blooddrip += 5;
3218 if (creature == wolftype && weaponactive == -1) {
3219 emit_sound_at(clawslicesound, victim->coords, 128.);
3221 victim->DoBloodBig(2, 175);
3224 award_bonus(id, spinecrusher);
3227 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3228 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3230 if (animTarget == knifefollowanim)
3231 victim->DoBloodBig(200, 210);
3232 if (animTarget == knifesneakattackanim) {
3233 XYZ footvel, footpoint;
3235 footpoint = weapons[weaponids[0]].tippoint;
3237 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3238 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3239 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3240 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3241 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3242 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3243 victim->DoBloodBig(200, 195);
3244 award_bonus(id, tracheotomy);
3246 if (animTarget == knifefollowanim) {
3247 award_bonus(id, Stabbonus);
3248 XYZ footvel, footpoint;
3250 footpoint = weapons[weaponids[0]].tippoint;
3252 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3253 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3254 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3255 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3256 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3257 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3260 victim->bloodloss += 10000;
3261 victim->velocity = 0;
3262 emit_sound_at(fleshstabsound, victim->coords);
3264 weapons[weaponids[weaponactive]].bloody = 2;
3265 weapons[weaponids[weaponactive]].blooddrip += 5;
3269 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3271 victim->velocity = 0;
3272 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3273 victim->skeleton.joints[i].velocity = 0;
3275 if (animTarget == knifefollowanim) {
3277 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3278 victim->skeleton.joints[i].velocity = 0;
3281 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3282 emit_sound_at(fleshstabremovesound, victim->coords);
3284 weapons[weaponids[weaponactive]].bloody = 2;
3285 weapons[weaponids[weaponactive]].blooddrip += 5;
3287 XYZ footvel, footpoint;
3289 footpoint = weapons[weaponids[0]].tippoint;
3291 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3292 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3293 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3294 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3295 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3296 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3300 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3301 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3302 award_bonus(id, backstab);
3306 XYZ footvel, footpoint;
3308 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3310 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3311 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3312 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3313 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3314 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3315 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3316 victim->DoBloodBig(200, 180);
3317 victim->DoBloodBig(200, 215);
3318 victim->bloodloss += 10000;
3319 victim->velocity = 0;
3320 emit_sound_at(fleshstabsound, victim->coords);
3322 weapons[weaponids[weaponactive]].bloody = 2;
3323 weapons[weaponids[weaponactive]].blooddrip += 5;
3327 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3329 victim->velocity = 0;
3330 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3331 victim->skeleton.joints[i].velocity = 0;
3333 if (weaponactive != -1) {
3334 emit_sound_at(fleshstabremovesound, victim->coords);
3336 weapons[weaponids[weaponactive]].bloody = 2;
3337 weapons[weaponids[weaponactive]].blooddrip += 5;
3339 XYZ footvel, footpoint;
3341 footpoint = weapons[weaponids[0]].tippoint;
3343 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3344 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3345 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3346 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3347 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3348 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3352 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3360 if (weaponactive == -1) {
3361 if (tutoriallevel != 1) {
3362 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3367 if (weaponactive != -1 || creature == wolftype)
3369 if (creature == rabbittype && weaponactive != -1)
3370 if (weapons[weaponids[0]].getType() == staff)
3373 if (weaponactive != -1) {
3374 victim->DoBloodBig(2 / victim->armorhead, 225);
3375 emit_sound_at(knifeslicesound, victim->coords);
3376 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3377 weapons[weaponids[weaponactive]].bloody = 1;
3378 weapons[weaponids[weaponactive]].blooddrip += 3;
3380 if (weaponactive == -1 && creature == wolftype) {
3381 emit_sound_at(clawslicesound, victim->coords, 128.);
3383 victim->DoBloodBig(2 / victim->armorhead, 175);
3387 award_bonus(id, Reversal);
3392 relative = facing * -1;
3394 Normalise(&relative);
3395 relative = DoRotation(relative, 0, 90, 0);
3397 Normalise(&relative);
3398 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3399 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3401 victim->jointVel(head) += relative * damagemult * 200;
3402 if (victim->damage < victim->damagetolerance - 100)
3403 victim->velocity = relative * 200;
3404 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3405 victim->velocity = 0;
3408 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3412 relative = facing * -1;
3414 Normalise(&relative);
3415 relative = DoRotation(relative, 0, 90, 0);
3417 Normalise(&relative);
3418 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3419 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3421 victim->jointVel(head) += relative * damagemult * 200;
3424 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3425 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3426 award_bonus(id, reverseko);
3432 if (frameTarget > animation[animCurrent].numframes - 1) {
3435 animTarget = getIdle();
3439 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3440 animTarget = rollanim;
3442 emit_sound_at(movewhooshsound, coords, 128.);
3444 if (animCurrent == staggerbackhighanim) {
3445 animTarget = getIdle();
3447 if (animCurrent == staggerbackhardanim) {
3448 animTarget = getIdle();
3450 if (animCurrent == removeknifeanim) {
3451 animTarget = getIdle();
3453 if (animCurrent == crouchremoveknifeanim) {
3454 animTarget = getCrouch();
3456 if (animCurrent == backhandspringanim) {
3457 animTarget = getIdle();
3459 if (animCurrent == dodgebackanim) {
3460 animTarget = getIdle();
3462 if (animCurrent == drawleftanim) {
3463 animTarget = getIdle();
3465 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3466 animTarget = getIdle();
3467 if (animCurrent == crouchdrawrightanim) {
3468 animTarget = getCrouch();
3470 if (weaponactive == -1)
3472 else if (weaponactive == 0) {
3474 if (num_weapons == 2) {
3476 buffer = weaponids[0];
3477 weaponids[0] = weaponids[1];
3478 weaponids[1] = buffer;
3482 if (weaponactive == -1) {
3483 emit_sound_at(knifesheathesound, coords, 128.);
3485 if (weaponactive != -1) {
3486 emit_sound_at(knifedrawsound, coords, 128.);
3489 if (animCurrent == rollanim) {
3490 animTarget = getCrouch();
3495 if (animTarget == walljumprightkickanim) {
3498 if (animTarget == walljumpleftkickanim) {
3501 animTarget = jumpdownanim;
3503 if (animCurrent == climbanim) {
3504 animTarget = getCrouch();
3506 coords += facing * .1;
3507 if (!isnormal(coords.x))
3518 if (animTarget == rabbitkickreversalanim) {
3519 animTarget = getCrouch();
3522 if (animTarget == jumpreversalanim) {
3523 animTarget = getCrouch();
3526 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3527 if (attackkeydown && animTarget != walljumpfrontanim) {
3529 float closestdist = -1;
3531 if (Person::players.size() > 1)
3532 for (unsigned i = 0; i < Person::players.size(); i++) {
3533 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3534 distance = distsq(&Person::players[i]->coords, &coords);
3535 if (closestdist == -1 || distance < closestdist) {
3536 closestdist = distance;
3541 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3542 victim = Person::players[closest];
3543 animTarget = walljumprightkickanim;
3545 XYZ rotatetarget = victim->coords - coords;
3546 Normalise(&rotatetarget);
3547 yaw = -asin(0 - rotatetarget.x);
3549 if (rotatetarget.z < 0)
3551 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3552 velocity = (victim->coords - coords) * 4;
3557 if (animTarget == walljumpbackanim) {
3558 animTarget = backflipanim;
3560 velocity = facing * -8;
3563 resume_stream(whooshsound);
3565 if (animTarget == walljumprightanim) {
3566 animTarget = rightflipanim;
3570 velocity = DoRotation(facing, 0, 30, 0) * -8;
3573 if (animTarget == walljumpfrontanim) {
3574 animTarget = frontflipanim;
3578 velocity = facing * 8;
3582 resume_stream(whooshsound);
3584 if (animTarget == walljumpleftanim) {
3585 if (attackkeydown) {
3587 float closestdist = -1;
3589 if (Person::players.size() > 1)
3590 for (unsigned i = 0; i < Person::players.size(); i++) {
3591 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3592 distance = distsq(&Person::players[i]->coords, &coords);
3593 if (closestdist == -1 || distance < closestdist) {
3594 closestdist = distance;
3599 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3600 victim = Person::players[closest];
3601 animTarget = walljumpleftkickanim;
3603 XYZ rotatetarget = victim->coords - coords;
3604 Normalise(&rotatetarget);
3605 yaw = -asin(0 - rotatetarget.x);
3607 if (rotatetarget.z < 0)
3609 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3610 velocity = (victim->coords - coords) * 4;
3615 if (animTarget != walljumpleftkickanim) {
3616 animTarget = leftflipanim;
3620 velocity = DoRotation(facing, 0, -30, 0) * -8;
3624 resume_stream(whooshsound);
3626 if (animTarget == sneakattackanim) {
3627 animCurrent = getCrouch();
3628 animTarget = getCrouch();
3635 transspeed = 1000000;
3636 targetheadyaw += 180;
3637 coords -= facing * .7;
3639 coords.y = terrain.getHeight(coords.x, coords.z);
3643 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3644 animTarget = getIdle();
3647 coords.y = terrain.getHeight(coords.x, coords.z);
3651 if (animCurrent == knifefollowanim) {
3652 animTarget = getIdle();
3655 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3656 float ycoords = oldcoords.y;
3657 animTarget = getStop();
3662 transspeed = 1000000;
3663 targetheadyaw += 180;
3664 if (!isnormal(coords.x))
3666 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3667 oldcoords = coords + facing * .5;
3668 else if (animCurrent == sweepreversalanim)
3669 oldcoords = coords + facing * 1.1;
3670 else if (animCurrent == upunchreversalanim) {
3671 oldcoords = coords + facing * 1.5;
3674 targetheadyaw += 180;
3677 } else if (animCurrent == knifeslashreversalanim) {
3678 oldcoords = coords + facing * .5;
3681 targetheadyaw += 90;
3684 } else if (animCurrent == staffspinhitreversalanim) {
3687 targetheadyaw += 180;
3692 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3694 oldcoords.y = ycoords;
3695 currentoffset = coords - oldcoords;
3701 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3706 if (animation[animTarget].attack == reversed) {
3708 if (animTarget == sweepreversedanim)
3710 animTarget = backhandspringanim;
3712 emit_sound_at(landsound, coords, 128);
3714 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3715 animTarget = rollanim;
3718 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3719 coords.y = oldcoords.y;
3721 if (animCurrent == knifeslashreversedanim) {
3722 animTarget = rollanim;
3727 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3728 coords.y = oldcoords.y;
3732 animTarget = jumpdownanim;
3735 animTarget = getIdle();
3737 animTarget = getIdle();
3738 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3739 animTarget = getIdle();
3741 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3742 coords.y = oldcoords.y;
3743 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3744 targetoffset.y = coords.y;
3746 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3747 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3748 currentoffset.y -= (coords.y - targetoffset.y);
3749 coords.y = targetoffset.y;
3751 normalsupdatedelay = 0;
3753 if (animCurrent == upunchanim) {
3754 animTarget = getStop();
3755 normalsupdatedelay = 0;
3758 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3762 if (num_weapons > 0)
3763 if (weapons[0].getType() == staff)
3769 rabbitkickragdoll = 1;
3771 if (animCurrent == rabbitkickreversedanim) {
3777 skeleton.spinny = 0;
3778 SolidHitBonus(!id); // FIXME: tricky id
3782 animTarget = rollanim;
3785 pause_sound(whooshsound);
3789 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3793 skeleton.spinny = 0;
3795 if (animCurrent == jumpreversedanim) {
3801 skeleton.spinny = 0;
3802 SolidHitBonus(!id); // FIXME: tricky id
3806 animTarget = rollanim;
3807 coords += facing * 2;
3809 pause_sound(whooshsound);
3814 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) {
3815 animTarget = getupfromfrontanim;
3817 } else if (animation[animCurrent].attack == normalattack) {
3818 animTarget = getIdle();
3821 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
3822 animTarget = blockhighleftstrikeanim;
3824 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
3825 animTarget = getIdle();
3828 if (animCurrent == spinkickanim && victim->skeleton.free) {
3829 if (creature == rabbittype)
3830 animTarget = fightidleanim;
3835 if (isIdle() && !wasIdle())
3836 normalsupdatedelay = 0;
3838 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
3839 animTarget = jumpdownanim;
3842 if (!skeleton.free) {
3844 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
3845 if (!isRun() || !wasRun()) {
3846 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3847 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
3848 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3849 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
3851 if (isRun() && wasRun()) {
3853 tempspeed = velspeed;
3854 if (tempspeed < 10 * speedmult)
3855 tempspeed = 10 * speedmult;
3856 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
3858 } else if (transspeed)
3859 target += multiplier * transspeed * speed * 2;
3861 if (!isRun() || !wasRun()) {
3862 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3863 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
3864 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3865 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
3869 if (animCurrent != animTarget)
3870 target = (target + oldtarget) / 2;
3873 frameCurrent = frameTarget;
3877 rot = targetrot * target;
3878 yaw += rot - oldrot;
3884 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
3886 for (int i = 0; i < skeleton.num_joints; i++) {
3887 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
3890 skeleton.FindForwards();
3892 for (int i = 0; i < skeleton.num_muscles; i++) {
3893 if (skeleton.muscles[i].visible) {
3894 skeleton.FindRotationMuscle(i, animTarget);
3897 for (int i = 0; i < skeleton.num_muscles; i++) {
3898 if (skeleton.muscles[i].visible) {
3899 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3900 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
3901 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
3902 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
3903 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
3904 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
3909 for (int i = 0; i < skeleton.num_joints; i++) {
3910 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
3913 skeleton.FindForwards();
3915 for (int i = 0; i < skeleton.num_muscles; i++) {
3916 if (skeleton.muscles[i].visible) {
3917 skeleton.FindRotationMuscle(i, animTarget);
3920 for (int i = 0; i < skeleton.num_muscles; i++) {
3921 if (skeleton.muscles[i].visible) {
3922 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3923 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
3924 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
3925 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
3926 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
3927 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
3928 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
3929 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
3930 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
3931 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
3932 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
3933 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
3937 if (frameCurrent >= animation[animCurrent].numframes)
3938 frameCurrent = animation[animCurrent].numframes - 1;
3940 oldanimCurrent = animCurrent;
3941 oldanimTarget = animTarget;
3942 oldframeTarget = frameTarget;
3943 oldframeCurrent = frameCurrent;
3945 for (int i = 0; i < skeleton.num_joints; i++) {
3946 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
3947 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
3949 offset = currentoffset * (1 - target) + targetoffset * target;
3950 for (int i = 0; i < skeleton.num_muscles; i++) {
3951 if (skeleton.muscles[i].visible) {
3952 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
3953 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
3954 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
3959 if (isLanding() && landhard) {
3962 animTarget = getLandhard();
3975 void Person::DoStuff()
3977 static XYZ terrainnormal;
3978 static XYZ flatfacing;
3979 static XYZ flatvelocity;
3980 static float flatvelspeed;
3984 static int bloodsize;
3985 static int startx, starty, endx, endy;
3986 static GLubyte color;
3987 static XYZ bloodvel;
3989 onfiredelay -= multiplier;
3990 if (onfiredelay < 0 && onfire) {
3991 if (Random() % 2 == 0) {
3997 crouchkeydowntime += multiplier;
3999 crouchkeydowntime = 0;
4000 jumpkeydowntime += multiplier;
4001 if (!jumpkeydown && skeleton.free)
4002 jumpkeydowntime = 0;
4004 if (hostile || damage > 0 || bloodloss > 0)
4007 if (isIdle() || isRun())
4010 if (num_weapons == 1 && weaponactive != -1)
4014 blooddimamount -= multiplier * .3;
4015 speechdelay -= multiplier;
4016 texupdatedelay -= multiplier;
4017 interestdelay -= multiplier;
4018 flamedelay -= multiplier;
4019 parriedrecently -= multiplier;
4021 victim = this->shared_from_this();
4026 speed = 1.1 * speedmult;
4028 speed = 1.0 * speedmult;
4030 rabbitkickragdoll = 0;
4034 if (id != 0 && (creature == rabbittype || difficulty != 2))
4036 if (id != 0 && creature == wolftype && difficulty == 2) {
4038 if (aitype != passivetype) {
4040 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) {
4046 if (animTarget == wolfrunninganim && !superruntoggle) {
4047 animTarget = getRun();
4051 if (weaponactive == -1 && num_weapons > 0) {
4052 if (weapons[weaponids[0]].getType() == staff) {
4058 burnt += multiplier;
4062 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4064 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4070 vel[0] = velocity.x;
4071 vel[1] = velocity.y;
4072 vel[2] = velocity.z;
4075 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4076 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4080 while (flamedelay < 0 && onfire) {
4082 howmany = abs(Random() % (skeleton.num_joints));
4083 if (skeleton.free) {
4084 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4085 flatfacing = skeleton.joints[howmany].position * scale + coords;
4087 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4088 flatvelocity = (coords - oldcoords) / multiplier / 2;
4090 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4093 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4095 howmany = abs(Random() % (skeleton.num_joints));
4096 if (skeleton.free) {
4097 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4098 flatfacing = skeleton.joints[howmany].position * scale + coords;
4100 flatvelocity = (coords - oldcoords) / multiplier / 2;
4101 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4103 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4107 bleeding -= multiplier * .3;
4108 if (bloodtoggle == 2) {
4109 skeleton.drawmodel.textureptr.bind();
4110 if ((bleeding <= 0) && (detail != 2))
4115 if (neckspurtamount > 0) {
4116 neckspurtamount -= multiplier;
4117 neckspurtdelay -= multiplier * 3;
4118 neckspurtparticledelay -= multiplier * 3;
4119 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4122 if (skeleton.free) {
4123 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4124 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4125 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4127 bloodvel.z = 5 * neckspurtamount;
4128 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4129 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4130 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4132 neckspurtparticledelay = .05;
4134 if (neckspurtdelay < 0) {
4139 if (deathbleeding > 0 && dead != 2) {
4140 if (deathbleeding < 5)
4141 bleeddelay -= deathbleeding * multiplier / 4;
4143 bleeddelay -= 5 * multiplier / 4;
4144 if (bleeddelay < 0 && bloodtoggle) {
4149 if (skeleton.free) {
4150 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4151 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4153 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4154 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4158 bloodloss += deathbleeding * multiplier * 80;
4159 deathbleeding -= multiplier * 1.6;
4160 if (deathbleeding < 0)
4162 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4163 if (weaponactive != -1) {
4164 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4165 weapons[weaponids[0]].velocity.x += .01;
4168 weaponids[0] = weaponids[num_weapons];
4169 if (weaponstuck == num_weapons)
4173 for (unsigned i = 0; i < Person::players.size(); i++) {
4174 Person::players[i]->wentforweapon = 0;
4186 if (!dead && creature == wolftype) {
4187 award_bonus(0, Wolfbonus);
4190 if (animTarget == knifefollowedanim && !skeleton.free) {
4191 for (int i = 0; i < skeleton.num_joints; i++) {
4192 skeleton.joints[i].velocity = 0;
4193 skeleton.joints[i].velocity.y = -2;
4196 if (id != 0 && unconscioustime > .1) {
4204 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4205 texupdatedelay = .12;
4207 bloodsize = 5 - realtexdetail;
4211 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4212 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4213 endx = startx + bloodsize;
4214 endy = starty + bloodsize;
4224 if (endx > skeleton.skinsize - 1) {
4225 endx = skeleton.skinsize - 1;
4228 if (endy > skeleton.skinsize - 1) {
4229 endy = skeleton.skinsize - 1;
4237 for (i = startx; i < endx; i++) {
4238 for (j = starty; j < endy; j++) {
4239 if (Random() % 2 == 0) {
4240 color = Random() % 85 + 170;
4241 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4242 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4243 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4244 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4249 skeleton.drawmodel.textureptr.bind();
4253 if (skeleton.free) {
4254 bleedx += 4 * direction / realtexdetail;
4256 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4258 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4260 bleedy -= 4 / realtexdetail;
4262 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4264 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4268 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4269 righthandmorphness = targetrighthandmorphness;
4270 righthandmorphstart = righthandmorphend;
4271 } else if (righthandmorphness > targetrighthandmorphness) {
4272 righthandmorphness -= multiplier * 4;
4273 } else if (righthandmorphness < targetrighthandmorphness) {
4274 righthandmorphness += multiplier * 4;
4277 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4278 lefthandmorphness = targetlefthandmorphness;
4279 lefthandmorphstart = lefthandmorphend;
4280 } else if (lefthandmorphness > targetlefthandmorphness) {
4281 lefthandmorphness -= multiplier * 4;
4282 } else if (lefthandmorphness < targetlefthandmorphness) {
4283 lefthandmorphness += multiplier * 4;
4286 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4287 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4288 tailmorphness = targettailmorphness;
4289 tailmorphstart = tailmorphend;
4290 } else if (tailmorphness > targettailmorphness) {
4291 tailmorphness -= multiplier * 10;
4292 } else if (tailmorphness < targettailmorphness) {
4293 tailmorphness += multiplier * 10;
4297 if (creature == wolftype) {
4298 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4299 tailmorphness = targettailmorphness;
4300 tailmorphstart = tailmorphend;
4301 } else if (tailmorphness > targettailmorphness) {
4302 tailmorphness -= multiplier * 2;
4303 } else if (tailmorphness < targettailmorphness) {
4304 tailmorphness += multiplier * 2;
4308 if (headmorphend == 3 || headmorphstart == 3) {
4309 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4310 headmorphness = targetheadmorphness;
4311 headmorphstart = headmorphend;
4312 } else if (headmorphness > targetheadmorphness) {
4313 headmorphness -= multiplier * 7;
4314 } else if (headmorphness < targetheadmorphness) {
4315 headmorphness += multiplier * 7;
4317 } else if (headmorphend == 5 || headmorphstart == 5) {
4318 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4319 headmorphness = targetheadmorphness;
4320 headmorphstart = headmorphend;
4321 } else if (headmorphness > targetheadmorphness) {
4322 headmorphness -= multiplier * 10;
4323 } else if (headmorphness < targetheadmorphness) {
4324 headmorphness += multiplier * 10;
4327 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4328 headmorphness = targetheadmorphness;
4329 headmorphstart = headmorphend;
4330 } else if (headmorphness > targetheadmorphness) {
4331 headmorphness -= multiplier * 4;
4332 } else if (headmorphness < targetheadmorphness) {
4333 headmorphness += multiplier * 4;
4337 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4338 chestmorphness = targetchestmorphness;
4339 chestmorphstart = chestmorphend;
4340 } else if (chestmorphness > targetchestmorphness) {
4341 chestmorphness -= multiplier;
4342 } else if (chestmorphness < targetchestmorphness) {
4343 chestmorphness += multiplier;
4346 if (dead != 2 && howactive <= typesleeping) {
4347 if (chestmorphstart == 0 && chestmorphend == 0) {
4349 targetchestmorphness = 1;
4352 if (chestmorphstart != 0 && chestmorphend != 0) {
4354 targetchestmorphness = 1;
4356 if (environment == snowyenvironment) {
4359 if (skeleton.free) {
4360 footvel = skeleton.specialforward[0] * -1;
4361 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4363 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4364 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4366 if (animTarget == sleepanim)
4367 footvel = DoRotation(footvel, 0, 90, 0);
4368 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4372 if (!dead && howactive < typesleeping) {
4373 blinkdelay -= multiplier * 2;
4374 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4376 targetheadmorphness = 1;
4378 blinkdelay = (float)(abs(Random() % 40)) / 5;
4380 if (headmorphstart == 3 && headmorphend == 3) {
4382 targetheadmorphness = 1;
4387 twitchdelay -= multiplier * 1.5;
4388 if (animTarget != hurtidleanim) {
4389 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4391 targetheadmorphness = 1;
4393 twitchdelay = (float)(abs(Random() % 40)) / 5;
4395 if (headmorphstart == 5 && headmorphend == 5) {
4397 targetheadmorphness = 1;
4401 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4402 twitchdelay3 -= multiplier * 1;
4403 if (Random() % 2 == 0) {
4404 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4405 righthandmorphness = 0;
4406 targetrighthandmorphness = 1;
4407 righthandmorphend = 1;
4408 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4410 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4411 righthandmorphness = 0;
4412 targetrighthandmorphness = 1;
4413 righthandmorphend = 0;
4416 if (Random() % 2 == 0) {
4417 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4418 lefthandmorphness = 0;
4419 targetlefthandmorphness = 1;
4420 lefthandmorphend = 1;
4421 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4423 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4424 lefthandmorphness = 0;
4425 targetlefthandmorphness = 1;
4426 lefthandmorphend = 0;
4432 if (creature == rabbittype) {
4433 if (howactive < typesleeping)
4434 twitchdelay2 -= multiplier * 1.5;
4436 twitchdelay2 -= multiplier * 0.5;
4437 if (howactive <= typesleeping) {
4438 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4440 targettailmorphness = 1;
4442 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4444 if (tailmorphstart == 1 && tailmorphend == 1) {
4446 targettailmorphness = 1;
4449 if (tailmorphstart == 2 && tailmorphend == 2) {
4451 targettailmorphness = 1;
4458 if (creature == wolftype) {
4459 twitchdelay2 -= multiplier * 1.5;
4460 if (tailmorphend != 0)
4461 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4463 targettailmorphness = 1;
4467 if (tailmorphend != 5)
4468 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4470 targettailmorphness = 1;
4474 if (twitchdelay2 <= 0) {
4475 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4477 targettailmorphness = 1;
4480 if (tailmorphstart == 1 && tailmorphend == 1) {
4482 targettailmorphness = 1;
4485 if (tailmorphstart == 2 && tailmorphend == 2) {
4487 targettailmorphness = 1;
4490 if (tailmorphstart == 3 && tailmorphend == 3) {
4492 targettailmorphness = 1;
4495 if (tailmorphstart == 4 && tailmorphend == 4) {
4497 targettailmorphness = 1;
4504 unconscioustime = 0;
4506 if (dead == 1 || howactive == typesleeping) {
4507 unconscioustime += multiplier;
4508 //If unconscious, close eyes and mouth
4509 if (righthandmorphend != 0)
4510 righthandmorphness = 0;
4511 righthandmorphend = 0;
4512 targetrighthandmorphness = 1;
4514 if (lefthandmorphend != 0)
4515 lefthandmorphness = 0;
4516 lefthandmorphend = 0;
4517 targetlefthandmorphness = 1;
4519 if (headmorphend != 3 && headmorphend != 5)
4522 targetheadmorphness = 1;
4526 if (howactive > typesleeping) {
4529 if (bloodtoggle && !bled) {
4530 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4532 if (bloodtoggle && !bled)
4533 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4534 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4535 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4539 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4544 if (dead == 2 || howactive > typesleeping) {
4545 //If dead, open mouth and hands
4546 if (righthandmorphend != 0)
4547 righthandmorphness = 0;
4548 righthandmorphend = 0;
4549 targetrighthandmorphness = 1;
4551 if (lefthandmorphend != 0)
4552 lefthandmorphness = 0;
4553 lefthandmorphend = 0;
4554 targetlefthandmorphness = 1;
4556 if (headmorphend != 2)
4559 targetheadmorphness = 1;
4562 if (stunned > 0 && !dead && headmorphend != 2) {
4563 if (headmorphend != 4)
4566 targetheadmorphness = 1;
4569 if (damage > damagetolerance && !dead) {
4572 unconscioustime = 0;
4574 if (creature == wolftype) {
4575 award_bonus(0, Wolfbonus);
4580 if (weaponactive != -1) {
4581 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4582 weapons[weaponids[0]].velocity.x += .01;
4585 weaponids[0] = weaponids[num_weapons];
4586 if (weaponstuck == num_weapons)
4590 for (unsigned i = 0; i < Person::players.size(); i++) {
4591 Person::players[i]->wentforweapon = 0;
4597 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4606 damage -= multiplier * 13;
4608 permanentdamage -= multiplier * 4;
4609 if (isIdle() || isCrouch()) {
4611 permanentdamage -= multiplier * 4;
4615 if (permanentdamage < 0)
4616 permanentdamage = 0;
4617 if (superpermanentdamage < 0)
4618 superpermanentdamage = 0;
4619 if (permanentdamage < superpermanentdamage) {
4620 permanentdamage = superpermanentdamage;
4622 if (damage < permanentdamage) {
4623 damage = permanentdamage;
4625 if (dead == 1 && damage < damagetolerance) {
4629 for (int i = 0; i < skeleton.num_joints; i++) {
4630 skeleton.joints[i].velocity = 0;
4633 if (permanentdamage > damagetolerance && dead != 2) {
4636 if (weaponactive != -1) {
4637 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4638 weapons[weaponids[0]].velocity.x += .01;
4641 weaponids[0] = weaponids[num_weapons];
4642 if (weaponstuck == num_weapons)
4646 for (unsigned i = 0; i < Person::players.size(); i++) {
4647 Person::players[i]->wentforweapon = 0;
4653 if (!dead && creature == wolftype) {
4654 award_bonus(0, Wolfbonus);
4657 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4658 award_bonus(id, touchofdeath);
4659 if (id != 0 && unconscioustime > .1) {
4667 emit_sound_at(breaksound, coords);
4670 if (skeleton.free == 1) {
4672 pause_sound(whooshsound);
4675 //If knocked over, open hands and close mouth
4676 if (righthandmorphend != 0)
4677 righthandmorphness = 0;
4678 righthandmorphend = 0;
4679 targetrighthandmorphness = 1;
4681 if (lefthandmorphend != 0)
4682 lefthandmorphness = 0;
4683 lefthandmorphend = 0;
4684 targetlefthandmorphness = 1;
4686 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4687 if (headmorphend != 0)
4690 targetheadmorphness = 1;
4694 skeleton.DoGravity(&scale);
4696 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4697 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4698 award_bonus(id, deepimpact);
4699 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4703 for (j = 0; j < skeleton.num_joints; j++) {
4704 average += skeleton.joints[j].position;
4708 coords += average * scale;
4709 for (j = 0; j < skeleton.num_joints; j++) {
4710 skeleton.joints[j].position -= average;
4712 average /= multiplier;
4715 for (int i = 0; i < skeleton.num_joints; i++) {
4716 velocity += skeleton.joints[i].velocity * scale;
4718 velocity /= skeleton.num_joints;
4720 if (!isnormal(velocity.x) && velocity.x) {
4724 if (findLength(&average) < 10 && dead && skeleton.free) {
4725 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4726 if (skeleton.longdead > 2000) {
4727 if (skeleton.longdead > 6000) {
4729 pause_sound(whooshsound);
4734 if (dead == 2 && bloodloss < damagetolerance) {
4736 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4738 if (bloodtoggle && !bled) {
4739 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4741 if (bloodtoggle && !bled)
4742 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4743 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4744 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4745 float size = .2 * 1.2;
4748 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4752 if (dead == 2 && bloodloss >= damagetolerance) {
4754 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4757 if (bloodtoggle && !bled) {
4758 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4760 if (bloodtoggle && !bled)
4761 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4762 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4763 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4767 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4774 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4775 bool canrecover = 1;
4776 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4777 startpoint = coords;
4780 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4782 if (velocity.y < -30)
4784 for (i = 0; i < objects.numobjects; i++) {
4785 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4786 colviewer = startpoint;
4787 coltarget = endpoint;
4788 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4797 terrainnormal = jointPos(groin) - jointPos(abdomen);
4798 if (joint(groin).locked && joint(abdomen).locked) {
4799 terrainnormal = jointPos(groin) - jointPos(abdomen);
4800 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4802 if (joint(abdomen).locked && joint(neck).locked) {
4803 terrainnormal = jointPos(abdomen) - jointPos(neck);
4804 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4806 if (joint(groin).locked && joint(neck).locked) {
4807 terrainnormal = jointPos(groin) - jointPos(neck);
4808 middle = (jointPos(groin) + jointPos(neck)) / 2;
4810 Normalise(&terrainnormal);
4812 targetyaw = -asin(0 - terrainnormal.x);
4813 targetyaw *= 360 / 6.28;
4814 if (terrainnormal.z < 0)
4815 targetyaw = 180 - targetyaw;
4819 animTarget = flipanim;
4820 crouchtogglekeydown = 1;
4825 animCurrent = tempanim;
4829 for (int i = 0; i < skeleton.num_joints; i++) {
4830 tempanimation.position[i][0] = skeleton.joints[i].position;
4831 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4836 if (findLength(&average) < 10 && !dead && skeleton.free) {
4837 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4838 if (skeleton.longdead > (damage + 500) * 1.5) {
4840 pause_sound(whooshsound);
4846 terrainnormal = jointPos(groin) - jointPos(abdomen);
4847 if (joint(groin).locked && joint(abdomen).locked) {
4848 terrainnormal = jointPos(groin) - jointPos(abdomen);
4849 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4851 if (joint(abdomen).locked && joint(neck).locked) {
4852 terrainnormal = jointPos(abdomen) - jointPos(neck);
4853 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4855 if (joint(groin).locked && joint(neck).locked) {
4856 terrainnormal = jointPos(groin) - jointPos(neck);
4857 middle = (jointPos(groin) + jointPos(neck)) / 2;
4859 Normalise(&terrainnormal);
4861 targetyaw = -asin(0 - terrainnormal.x);
4862 targetyaw *= 360 / 6.28;
4863 if (terrainnormal.z < 0)
4864 targetyaw = 180 - targetyaw;
4867 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
4870 if (skeleton.forward.y < 0) {
4871 animTarget = getupfrombackanim;
4875 if (skeleton.forward.y > -.3) {
4876 animTarget = getupfromfrontanim;
4884 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
4885 animTarget = rollanim;
4886 targetyaw = lookyaw;
4903 if ( !leftkeydown && !rightkeydown)
4910 if (abs(targettilt2) > 50)
4912 animCurrent = tempanim;
4915 tilt2 = targettilt2;
4917 if (middle.y > 0 && animTarget != rollanim)
4918 targetoffset.y = middle.y + 1;
4920 for (int i = 0; i < skeleton.num_joints; i++) {
4921 tempanimation.position[i][0] = skeleton.joints[i].position;
4922 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4929 if (num_weapons > 0)
4930 if (weapons[0].getType() == staff)
4932 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
4933 if (velocity.y > -30) {
4935 tempvelocity = velocity;
4936 Normalise(&tempvelocity);
4937 targetyaw = -asin(0 - tempvelocity.x);
4938 targetyaw *= 360 / 6.28;
4940 targetyaw = 180 - targetyaw;
4944 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
4945 animTarget = rollanim;
4948 animTarget = backhandspringanim;
4954 emit_sound_at(movewhooshsound, coords, 128.);
4956 animCurrent = animTarget;
4957 frameCurrent = frameTarget - 1;
4969 if (skeleton.freefall == 0)
4974 if (aitype != passivetype || skeleton.free == 1)
4975 if (findLengthfast(&velocity) > .1)
4976 for (i = 0; i < objects.numobjects; i++) {
4977 if (objects.type[i] == firetype)
4978 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) {
4980 if (!objects.onfire[i]) {
4981 emit_sound_at(firestartsound, objects.position[i]);
4983 objects.onfire[i] = 1;
4986 if (objects.onfire[i]) {
4991 if (objects.type[i] == bushtype)
4992 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) {
4994 if (!objects.onfire[i]) {
4995 emit_sound_at(firestartsound, objects.position[i]);
4997 objects.onfire[i] = 1;
5001 if (objects.onfire[i]) {
5005 if (objects.messedwith[i] <= 0) {
5009 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5012 envsound[numenvsounds] = coords;
5013 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5014 envsoundlife[numenvsounds] = .4;
5019 if (environment == grassyenvironment)
5020 howmany = findLength(&velocity) * 4;
5021 if (environment == snowyenvironment)
5022 howmany = findLength(&velocity) * 2;
5024 if (environment != desertenvironment)
5025 for (j = 0; j < howmany; j++) {
5026 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5027 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5028 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5031 pos.x += float(abs(Random() % 100) - 50) / 200;
5032 pos.y += float(abs(Random() % 100) - 50) / 200;
5033 pos.z += float(abs(Random() % 100) - 50) / 200;
5034 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);
5035 Sprite::setLastSpriteSpecial(1);
5037 howmany = findLength(&velocity) * 4;
5039 if (environment == snowyenvironment)
5040 for (j = 0; j < howmany; j++) {
5041 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5042 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5043 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5046 pos.x += float(abs(Random() % 100) - 50) / 200;
5047 pos.y += float(abs(Random() % 100) - 50) / 200;
5048 pos.z += float(abs(Random() % 100) - 50) / 200;
5049 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5050 Sprite::setLastSpriteSpecial(2);
5053 objects.rotx[i] += velocity.x * multiplier * 6;
5054 objects.roty[i] += velocity.z * multiplier * 6;
5055 objects.messedwith[i] = .5;
5058 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5059 if (objects.pitch[i] == 0)
5062 tempcoord = coords - objects.position[i];
5063 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5064 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5065 tempcoord += objects.position[i];
5067 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]) {
5068 if (objects.messedwith[i] <= 0) {
5072 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5075 envsound[numenvsounds] = coords;
5076 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5077 envsoundlife[numenvsounds] = .4;
5082 if (environment == grassyenvironment)
5083 howmany = findLength(&velocity) * 4;
5084 if (environment == snowyenvironment)
5085 howmany = findLength(&velocity) * 2;
5087 if (environment != desertenvironment)
5088 for (j = 0; j < howmany; j++) {
5089 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5090 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5091 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5093 pos += velocity * .1;
5095 pos.x += float(abs(Random() % 100) - 50) / 150;
5096 pos.y += float(abs(Random() % 100) - 50) / 150;
5097 pos.z += float(abs(Random() % 100) - 50) / 150;
5098 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);
5099 Sprite::setLastSpriteSpecial(1);
5101 howmany = findLength(&velocity) * 4;
5103 if (environment == snowyenvironment)
5104 for (j = 0; j < howmany; j++) {
5105 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5106 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5107 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5109 pos += velocity * .1;
5111 pos.x += float(abs(Random() % 100) - 50) / 150;
5112 pos.y += float(abs(Random() % 100) - 50) / 150;
5113 pos.z += float(abs(Random() % 100) - 50) / 150;
5114 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5115 Sprite::setLastSpriteSpecial(2);
5118 objects.messedwith[i] = .5;
5123 if (!skeleton.free) {
5126 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5129 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5131 if (tutoriallevel == 1 && id != 0)
5133 if (play && aitype != playercontrolled) {
5134 int whichsound = -1;
5135 i = abs(Random() % 4);
5136 if (speechdelay <= 0) {
5137 if (creature == rabbittype) {
5139 whichsound = rabbitchitter;
5141 whichsound = rabbitchitter2;
5143 if (creature == wolftype) {
5145 whichsound = growlsound;
5147 whichsound = growl2sound;
5152 if (whichsound != -1) {
5153 emit_sound_at(whichsound, coords);
5157 if (animTarget == staggerbackhighanim)
5159 if (animTarget == staggerbackhardanim)
5161 staggerdelay -= multiplier;
5162 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5164 if (velocity.y < -30 && animTarget == jumpdownanim)
5166 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5167 animTarget = getIdle();
5171 weaponmissdelay -= multiplier;
5172 highreversaldelay -= multiplier;
5173 lowreversaldelay -= multiplier;
5174 lastcollide -= multiplier;
5175 skiddelay -= multiplier;
5176 if (!isnormal(velocity.x) && velocity.x) {
5179 if (!isnormal(targettilt) && targettilt) {
5182 if (!isnormal(targettilt2) && targettilt2) {
5185 if (!isnormal(targetyaw) && targetyaw) {
5189 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5190 //open hands and close mouth
5191 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5192 righthandmorphness = 0;
5193 righthandmorphend = 0;
5194 targetrighthandmorphness = 1;
5197 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5198 lefthandmorphness = 0;
5199 lefthandmorphend = 0;
5200 targetlefthandmorphness = 1;
5203 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5206 targetheadmorphness = 1;
5210 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) {
5211 //open hands and mouth
5212 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5213 righthandmorphness = 0;
5214 righthandmorphend = 0;
5215 targetrighthandmorphness = 1;
5218 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5219 lefthandmorphness = 0;
5220 lefthandmorphend = 0;
5221 targetlefthandmorphness = 1;
5224 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5227 targetheadmorphness = 1;
5231 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5232 //close hands and mouth
5233 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5234 righthandmorphness = 0;
5235 righthandmorphend = 1;
5236 targetrighthandmorphness = 1;
5239 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5240 lefthandmorphness = 0;
5241 lefthandmorphend = 1;
5242 targetlefthandmorphness = 1;
5245 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5248 targetheadmorphness = 1;
5252 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) {
5253 //close hands and yell
5254 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5255 righthandmorphness = 0;
5256 righthandmorphend = 1;
5257 targetrighthandmorphness = 1;
5260 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5261 lefthandmorphness = 0;
5262 lefthandmorphend = 1;
5263 targetlefthandmorphness = 1;
5266 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5269 targetheadmorphness = 1;
5276 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5277 (victim->aitype != searchtype) && (aitype != passivetype) &&
5278 (aitype != searchtype) && (victim->id < Person::players.size())) {
5279 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5283 if (!dead && animTarget != hurtidleanim)
5284 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5285 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5288 targetheadmorphness = 1;
5292 if (weaponactive != -1) {
5293 if (weapons[weaponids[weaponactive]].getType() != staff) {
5294 righthandmorphstart = 1;
5295 righthandmorphend = 1;
5297 if (weapons[weaponids[weaponactive]].getType() == staff) {
5298 righthandmorphstart = 2;
5299 righthandmorphend = 2;
5301 targetrighthandmorphness = 1;
5304 terrainnormal = terrain.getNormal(coords.x, coords.z);
5306 if (animation[animTarget].attack != reversal) {
5307 if (!isnormal(coords.x))
5315 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5316 facing = flatfacing;
5317 ReflectVector(&facing, terrainnormal);
5320 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5322 targettilt2 = -facing.y * 20;
5327 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5329 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5330 flatvelocity = velocity;
5332 flatvelspeed = findLength(&flatvelocity);
5333 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5334 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5339 if (targettilt > 25)
5341 if (targettilt < -25)
5345 if (targettilt2 > 45)
5347 if (targettilt2 < -45)
5349 if (abs(tilt2 - targettilt2) < multiplier * 400)
5350 tilt2 = targettilt2;
5351 else if (tilt2 > targettilt2) {
5352 tilt2 -= multiplier * 400;
5353 } else if (tilt2 < targettilt2) {
5354 tilt2 += multiplier * 400;
5356 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5363 if (!isnormal(targettilt) && targettilt) {
5366 if (!isnormal(targettilt2) && targettilt2) {
5371 if (animTarget == rabbittackleanim) {
5372 velocity += facing * multiplier * speed * 700 * scale;
5373 velspeed = findLength(&velocity);
5374 if (velspeed > speed * 65 * scale) {
5375 velocity /= velspeed;
5376 velspeed = speed * 65 * scale;
5377 velocity *= velspeed;
5379 velocity.y += gravity * multiplier * 20;
5380 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5381 velspeed = findLength(&velocity);
5382 velocity = flatfacing * velspeed;
5384 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5385 if (isRun() || animTarget == rabbitkickanim) {
5386 velocity += facing * multiplier * speed * 700 * scale;
5387 velspeed = findLength(&velocity);
5388 if (velspeed > speed * 45 * scale) {
5389 velocity /= velspeed;
5390 velspeed = speed * 45 * scale;
5391 velocity *= velspeed;
5393 velocity.y += gravity * multiplier * 20;
5394 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5395 velspeed = findLength(&velocity);
5396 if (velspeed < speed * 30 * scale)
5397 velspeed = speed * 30 * scale;
5398 velocity = flatfacing * velspeed;
5400 } else if (isRun()) {
5401 velocity += facing * multiplier * speed * 700 * scale;
5402 velspeed = findLength(&velocity);
5403 if (creature == rabbittype) {
5404 if (velspeed > speed * 55 * scale) {
5405 velocity /= velspeed;
5406 velspeed = speed * 55 * scale;
5407 velocity *= velspeed;
5410 if (creature == wolftype) {
5411 if (velspeed > speed * 75 * scale) {
5412 velocity /= velspeed;
5413 velspeed = speed * 75 * scale;
5414 velocity *= velspeed;
5417 velocity.y += gravity * multiplier * 20;
5418 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5419 velspeed = findLength(&velocity);
5420 velocity = flatfacing * velspeed;
5423 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5424 velocity += facing * multiplier * speed * 700 * scale;
5425 velspeed = findLength(&velocity);
5426 if (velspeed > speed * 45 * scale) {
5427 velocity /= velspeed;
5428 velspeed = speed * 45 * scale;
5429 velocity *= velspeed;
5431 velocity.y += gravity * multiplier * 20;
5432 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5433 velspeed = findLength(&velocity);
5434 velocity = flatfacing * velspeed;
5437 if (animTarget == sneakanim || animTarget == walkanim) {
5438 velocity += facing * multiplier * speed * 700 * scale;
5439 velspeed = findLength(&velocity);
5440 if (velspeed > speed * 12 * scale) {
5441 velocity /= velspeed;
5442 velspeed = speed * 12 * scale;
5443 velocity *= velspeed;
5445 velocity.y += gravity * multiplier * 20;
5446 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5447 velspeed = findLength(&velocity);
5448 velocity = flatfacing * velspeed;
5451 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5452 velocity += facing * multiplier * speed * 700 * scale;
5453 velspeed = findLength(&velocity);
5454 if (velspeed > speed * 2 * scale) {
5455 velocity /= velspeed;
5456 velspeed = speed * 2 * scale;
5457 velocity *= velspeed;
5459 velocity.y += gravity * multiplier * 20;
5460 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5461 velspeed = findLength(&velocity);
5462 velocity = flatfacing * velspeed;
5466 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5467 velocity -= facing * multiplier * speed * 700 * scale;
5468 velspeed = findLength(&velocity);
5469 if (velspeed > speed * 2 * scale) {
5470 velocity /= velspeed;
5471 velspeed = speed * 2 * scale;
5472 velocity *= velspeed;
5474 velocity.y += gravity * multiplier * 20;
5475 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5476 velspeed = findLength(&velocity);
5477 velocity = flatfacing * velspeed * -1;
5480 if (animTarget == fightsidestep) {
5481 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5482 velspeed = findLength(&velocity);
5483 if (velspeed > speed * 12 * scale) {
5484 velocity /= velspeed;
5485 velspeed = speed * 12 * scale;
5486 velocity *= velspeed;
5488 velocity.y += gravity * multiplier * 20;
5489 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5490 velspeed = findLength(&velocity);
5491 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5494 if (animTarget == staggerbackhighanim) {
5495 coords -= facing * multiplier * speed * 16 * scale;
5498 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5499 coords -= facing * multiplier * speed * 20 * scale;
5503 if (animTarget == backhandspringanim) {
5504 //coords-=facing*multiplier*50*scale;
5505 velocity += facing * multiplier * speed * 700 * scale * -1;
5506 velspeed = findLength(&velocity);
5507 if (velspeed > speed * 50 * scale) {
5508 velocity /= velspeed;
5509 velspeed = speed * 50 * scale;
5510 velocity *= velspeed;
5512 velocity.y += gravity * multiplier * 20;
5513 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5514 velspeed = findLength(&velocity);
5515 velocity = flatfacing * velspeed * -1;
5517 if (animTarget == dodgebackanim) {
5518 //coords-=facing*multiplier*50*scale;
5519 velocity += facing * multiplier * speed * 700 * scale * -1;
5520 velspeed = findLength(&velocity);
5521 if (velspeed > speed * 60 * scale) {
5522 velocity /= velspeed;
5523 velspeed = speed * 60 * scale;
5524 velocity *= velspeed;
5526 velocity.y += gravity * multiplier * 20;
5527 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5528 velspeed = findLength(&velocity);
5529 velocity = flatfacing * velspeed * -1;
5532 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5533 velspeed = findLength(&velocity);
5537 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5538 velocity.y += gravity * multiplier;
5541 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5542 coords += velocity * multiplier;
5544 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5545 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5548 if (animTarget == jumpupanim) {
5550 animTarget = getIdle();
5557 pause_sound(whooshsound);
5558 OPENAL_SetVolume(channels[whooshsound], 0);
5561 if (animTarget == jumpdownanim || isFlip()) {
5562 if (isFlip())jumppower = -4;
5563 animTarget = getLanding();
5564 emit_sound_at(landsound, coords, 128.);
5567 envsound[numenvsounds] = coords;
5568 envsoundvol[numenvsounds] = 16;
5569 envsoundlife[numenvsounds] = .4;
5575 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5576 coords.y += gravity * multiplier * 2;
5577 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5578 coords.y = terrain.getHeight(coords.x, coords.z);
5583 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)) {
5584 velspeed = findLength(&velocity);
5586 if (velspeed < multiplier * 300 * scale) {
5589 velocity -= velocity / velspeed * multiplier * 300 * scale;
5590 if (velspeed > 5 && (isLanding() || isLandhard())) {
5591 skiddingdelay += multiplier;
5592 if (skiddelay <= 0) {
5602 velspeed = findLength(&velocity);
5604 if (velspeed < multiplier * 600 * scale) {
5607 velocity -= velocity / velspeed * multiplier * 600 * scale;
5609 if (velspeed > 5 && (isLanding() || isLandhard())) {
5610 skiddingdelay += multiplier;
5611 if (skiddelay <= 0) {
5620 if (skiddingdelay < 0)
5621 skiddingdelay += multiplier;
5622 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5624 if (!onterrain || environment == grassyenvironment) {
5625 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5627 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5631 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5632 terrainnormal = victim->coords - coords;
5633 Normalise(&terrainnormal);
5634 targetyaw = -asin(0 - terrainnormal.x);
5635 targetyaw *= 360 / 6.28;
5636 if (terrainnormal.z < 0)
5637 targetyaw = 180 - targetyaw;
5638 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5641 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5642 targetyaw = victim->targetyaw;
5644 if (animTarget == rabbittacklinganim) {
5645 coords = victim->coords;
5648 skeleton.oldfree = skeleton.free;
5652 midterrain.x = terrain.size * terrain.scale / 2;
5653 midterrain.z = terrain.size * terrain.scale / 2;
5654 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5656 tempposit = coords - midterrain;
5658 Normalise(&tempposit);
5659 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5660 coords.x = tempposit.x + midterrain.x;
5661 coords.z = tempposit.z + midterrain.z;
5667 * inverse kinematics helper function
5669 void IKHelper(Person *p, float interp)
5671 XYZ point, newpoint, change, change2;
5672 float heightleft, heightright;
5674 // TODO: implement localToWorld and worldToLocal
5675 // but keep in mind it won't be the same math if player is ragdolled or something
5676 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5677 // then comb through code for places where to use it
5679 // point = localToWorld(jointPos(leftfoot))
5680 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5681 // adjust height of foot
5682 heightleft = terrain.getHeight(point.x, point.z) + .04;
5683 point.y = heightleft;
5684 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5685 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5686 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5687 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5688 // move ankle along with foot
5689 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5690 // average knee pos between old and new pos
5691 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5693 // do same as above for right leg
5694 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5695 heightright = terrain.getHeight(point.x, point.z) + .04;
5696 point.y = heightright;
5697 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5698 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5699 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5700 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5701 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5703 // fix up skeleton now that we've moved body parts?
5704 p->skeleton.DoConstraints(&p->coords, &p->scale);
5711 int Person::DrawSkeleton()
5713 int oldplayerdetail;
5714 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5715 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5725 glAlphaFunc(GL_GREATER, 0.0001);
5727 float terrainheight;
5731 if (!isnormal(tilt))
5733 if (!isnormal(tilt2))
5735 oldplayerdetail = playerdetail;
5737 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5740 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5743 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5748 if (playerdetail != oldplayerdetail) {
5750 normalsupdatedelay = 0;
5752 static float updatedelaychange;
5753 static float morphness;
5754 static float framemult;
5756 skeleton.FindForwards();
5757 if (howactive == typesittingwall) {
5758 skeleton.specialforward[1] = 0;
5759 skeleton.specialforward[1].z = 1;
5765 static int weaponattachmuscle;
5766 static int weaponrotatemuscle;
5767 static XYZ weaponpoint;
5768 static int start, endthing;
5769 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5770 if (!isSleeping() && !isSitting()) {
5771 // TODO: give these meaningful names
5772 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5773 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5774 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5775 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5777 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5779 if (creature == wolftype)
5783 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5784 IKHelper(this, target);
5785 if (creature == wolftype)
5786 IKHelper(this, target);
5789 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5790 IKHelper(this, 1 - target);
5791 if (creature == wolftype)
5792 IKHelper(this, 1 - target);
5796 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()))
5799 targetheadyaw = -targetyaw;
5800 targetheadpitch = 0;
5801 if (animation[animTarget].attack == 3)
5802 targetheadyaw += 180;
5804 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5805 skeleton.drawmodel.vertex[i] = 0;
5806 skeleton.drawmodel.vertex[i].y = 999;
5808 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5809 skeleton.drawmodellow.vertex[i] = 0;
5810 skeleton.drawmodellow.vertex[i].y = 999;
5812 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5813 skeleton.drawmodelclothes.vertex[i] = 0;
5814 skeleton.drawmodelclothes.vertex[i].y = 999;
5816 for (int i = 0; i < skeleton.num_muscles; i++) {
5817 // convenience renames
5818 const int p1 = skeleton.muscles[i].parent1->label;
5819 const int p2 = skeleton.muscles[i].parent2->label;
5821 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
5826 if (p1 == righthand || p2 == righthand) {
5827 morphness = righthandmorphness;
5828 start = righthandmorphstart;
5829 endthing = righthandmorphend;
5831 if (p1 == lefthand || p2 == lefthand) {
5832 morphness = lefthandmorphness;
5833 start = lefthandmorphstart;
5834 endthing = lefthandmorphend;
5836 if (p1 == head || p2 == head) {
5837 morphness = headmorphness;
5838 start = headmorphstart;
5839 endthing = headmorphend;
5841 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
5842 morphness = chestmorphness;
5843 start = chestmorphstart;
5844 endthing = chestmorphend;
5846 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
5847 morphness = tailmorphness;
5848 start = tailmorphstart;
5849 endthing = tailmorphend;
5852 skeleton.FindRotationMuscle(i, animTarget);
5853 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5854 glMatrixMode(GL_MODELVIEW);
5858 glRotatef(tilt2, 1, 0, 0);
5860 glRotatef(tilt, 0, 0, 1);
5863 glTranslatef(mid.x, mid.y, mid.z);
5865 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
5866 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
5868 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
5869 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
5871 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
5872 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
5874 if (playerdetail || skeleton.free == 3) {
5875 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
5876 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
5877 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
5878 glMatrixMode(GL_MODELVIEW);
5880 if (p1 == abdomen || p2 == abdomen)
5881 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
5882 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
5883 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
5884 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5885 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
5886 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
5887 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
5888 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5889 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
5890 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
5891 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
5892 if (p1 == head || p2 == head)
5893 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
5894 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
5895 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
5896 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5897 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
5898 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
5899 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
5903 if (!playerdetail || skeleton.free == 3) {
5904 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
5905 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
5906 glMatrixMode(GL_MODELVIEW);
5908 if (p1 == abdomen || p2 == abdomen)
5909 glTranslatef(v0.x * proportionbody.x,
5910 v0.y * proportionbody.y,
5911 v0.z * proportionbody.z);
5912 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5913 glTranslatef(v0.x * proportionarms.x,
5914 v0.y * proportionarms.y,
5915 v0.z * proportionarms.z);
5916 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5917 glTranslatef(v0.x * proportionlegs.x,
5918 v0.y * proportionlegs.y,
5919 v0.z * proportionlegs.z);
5920 if (p1 == head || p2 == head)
5921 glTranslatef(v0.x * proportionhead.x,
5922 v0.y * proportionhead.y,
5923 v0.z * proportionhead.z);
5925 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5926 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
5927 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
5928 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
5934 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
5935 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5937 glMatrixMode(GL_MODELVIEW);
5941 glRotatef(tilt2, 1, 0, 0);
5943 glRotatef(tilt, 0, 0, 1);
5944 glTranslatef(mid.x, mid.y, mid.z);
5945 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
5946 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
5948 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
5949 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
5951 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
5952 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
5954 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
5955 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
5956 glMatrixMode(GL_MODELVIEW);
5958 if (p1 == abdomen || p2 == abdomen)
5959 glTranslatef(v0.x * proportionbody.x,
5960 v0.y * proportionbody.y,
5961 v0.z * proportionbody.z);
5962 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5963 glTranslatef(v0.x * proportionarms.x,
5964 v0.y * proportionarms.y,
5965 v0.z * proportionarms.z);
5966 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5967 glTranslatef(v0.x * proportionlegs.x,
5968 v0.y * proportionlegs.y,
5969 v0.z * proportionlegs.z);
5970 if (p1 == head || p2 == head)
5971 glTranslatef(v0.x * proportionhead.x,
5972 v0.y * proportionhead.y,
5973 v0.z * proportionhead.z);
5974 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5975 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
5976 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
5977 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
5982 updatedelay = 1 + (float)(Random() % 100) / 1000;
5984 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
5985 normalsupdatedelay = 1;
5986 if (playerdetail || skeleton.free == 3)
5987 skeleton.drawmodel.CalculateNormals(0);
5988 if (!playerdetail || skeleton.free == 3)
5989 skeleton.drawmodellow.CalculateNormals(0);
5990 if (skeleton.clothes)
5991 skeleton.drawmodelclothes.CalculateNormals(0);
5993 if (playerdetail || skeleton.free == 3)
5994 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
5995 if (!playerdetail || skeleton.free == 3)
5996 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
5997 if (skeleton.clothes) {
5998 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6003 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6004 if (updatedelaychange > -realmultiplier * 30)
6005 updatedelaychange = -realmultiplier * 30;
6006 if (updatedelaychange > -framemult * 4)
6007 updatedelaychange = -framemult * 4;
6008 if (skeleton.free == 1)
6009 updatedelaychange *= 6;
6011 updatedelaychange *= 8;
6012 updatedelay += updatedelaychange;
6014 glMatrixMode(GL_MODELVIEW);
6016 glTranslatef(coords.x, coords.y - .02, coords.z);
6017 if (!skeleton.free) {
6018 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6019 glRotatef(yaw, 0, 1, 0);
6023 glColor4f(.4, 1, .4, 1);
6024 glDisable(GL_LIGHTING);
6025 glDisable(GL_TEXTURE_2D);
6028 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6029 XYZ &v0 = skeleton.drawmodel.vertex[i];
6030 glVertex3f(v0.x, v0.y, v0.z);
6036 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6037 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6038 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6039 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6040 glVertex3f(v0.x, v0.y, v0.z);
6041 glVertex3f(v1.x, v1.y, v1.z);
6042 glVertex3f(v1.x, v1.y, v1.z);
6043 glVertex3f(v2.x, v2.y, v2.z);
6044 glVertex3f(v2.x, v2.y, v2.z);
6045 glVertex3f(v0.x, v0.y, v0.z);
6051 terrainlight = terrain.getLighting(coords.x, coords.z);
6052 distance = distsq(&viewer, &coords);
6053 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6057 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6058 if (terrainheight < 1)
6060 if (terrainheight > 1.7)
6061 terrainheight = 1.7;
6064 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6065 glDisable(GL_BLEND);
6066 glAlphaFunc(GL_GREATER, 0.0001);
6067 glEnable(GL_TEXTURE_2D);
6069 glDisable(GL_TEXTURE_2D);
6070 glColor4f(.7, .35, 0, .5);
6072 glEnable(GL_LIGHTING);
6075 if (tutoriallevel && id != 0) {
6076 glColor4f(.7, .7, .7, 0.6);
6078 glEnable(GL_LIGHTING);
6080 if (canattack && cananger)
6081 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6082 glDisable(GL_TEXTURE_2D);
6083 glColor4f(1, 0, 0, 0.8);
6085 glMatrixMode(GL_TEXTURE);
6087 glTranslatef(0, -smoketex, 0);
6088 glTranslatef(-smoketex, 0, 0);
6092 if ((tutoriallevel && id != 0))
6093 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6095 skeleton.drawmodel.draw();
6098 if (!playerdetail) {
6099 if ((tutoriallevel && id != 0))
6100 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6102 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6105 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6106 if (tutoriallevel && id != 0) {
6108 glMatrixMode(GL_MODELVIEW);
6109 glEnable(GL_TEXTURE_2D);
6110 glColor4f(.7, .7, .7, 0.6);
6112 glEnable(GL_LIGHTING);
6114 if (canattack && cananger)
6115 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6116 glDisable(GL_TEXTURE_2D);
6117 glColor4f(1, 0, 0, 0.8);
6119 glMatrixMode(GL_TEXTURE);
6121 glTranslatef(0, -smoketex * .6, 0);
6122 glTranslatef(smoketex * .6, 0, 0);
6125 if ((tutoriallevel && id != 0))
6126 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6128 skeleton.drawmodel.draw();
6131 if (!playerdetail) {
6132 if ((tutoriallevel && id != 0))
6133 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6135 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6140 if (tutoriallevel && id != 0) {
6142 glMatrixMode(GL_MODELVIEW);
6143 glEnable(GL_TEXTURE_2D);
6145 if (skeleton.clothes) {
6149 skeleton.drawmodelclothes.draw();
6151 skeleton.drawmodelclothes.drawimmediate();
6157 if (num_weapons > 0) {
6158 for (k = 0; k < num_weapons; k++) {
6160 if (weaponactive == k) {
6161 if (weapons[i].getType() != staff) {
6162 for (j = 0; j < skeleton.num_muscles; j++) {
6163 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6164 weaponattachmuscle = j;
6167 for (j = 0; j < skeleton.num_muscles; j++) {
6168 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) {
6169 weaponrotatemuscle = j;
6172 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6173 if (creature == wolftype)
6174 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6176 if (weapons[i].getType() == staff) {
6177 for (j = 0; j < skeleton.num_muscles; j++) {
6178 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6179 weaponattachmuscle = j;
6182 for (j = 0; j < skeleton.num_muscles; j++) {
6183 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) {
6184 weaponrotatemuscle = j;
6187 //weaponpoint=jointPos(rightwrist);
6188 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6189 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6190 XYZ tempnormthing, vec1, vec2;
6191 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6192 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6193 CrossProduct(&vec1, &vec2, &tempnormthing);
6194 Normalise(&tempnormthing);
6195 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6196 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6199 if (weaponactive != k && weaponstuck != k) {
6200 if (weapons[i].getType() == knife)
6201 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6202 if (weapons[i].getType() == sword)
6203 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6204 if (weapons[i].getType() == staff)
6205 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6206 for (j = 0; j < skeleton.num_muscles; j++) {
6207 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) {
6208 weaponrotatemuscle = j;
6212 if (weaponstuck == k) {
6213 if (weaponstuckwhere == 0)
6214 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6216 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6217 for (j = 0; j < skeleton.num_muscles; j++) {
6218 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) {
6219 weaponrotatemuscle = j;
6223 if (skeleton.free) {
6224 weapons[i].position = weaponpoint * scale + coords;
6225 weapons[i].bigrotation = 0;
6226 weapons[i].bigtilt = 0;
6227 weapons[i].bigtilt2 = 0;
6229 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;
6230 weapons[i].bigrotation = yaw;
6231 weapons[i].bigtilt = tilt;
6232 weapons[i].bigtilt2 = tilt2;
6234 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6235 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6236 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6237 if (weaponactive == k) {
6238 if (weapons[i].getType() == knife) {
6239 weapons[i].smallrotation = 180;
6240 weapons[i].smallrotation2 = 0;
6241 if (isCrouch() || wasCrouch()) {
6242 weapons[i].smallrotation2 = 20;
6244 if (animTarget == hurtidleanim) {
6245 weapons[i].smallrotation2 = 50;
6247 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6248 XYZ temppoint1, temppoint2, tempforward;
6251 temppoint1 = jointPos(righthand);
6252 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6253 distance = findDistance(&temppoint1, &temppoint2);
6254 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6255 weapons[i].rotation2 *= 360 / 6.28;
6258 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6259 weapons[i].rotation1 *= 360 / 6.28;
6260 weapons[i].rotation3 = 0;
6261 weapons[i].smallrotation = -90;
6262 weapons[i].smallrotation2 = 0;
6263 if (temppoint1.x > temppoint2.x)
6264 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6266 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6267 XYZ temppoint1, temppoint2, tempforward;
6270 temppoint1 = jointPos(righthand);
6271 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6272 distance = findDistance(&temppoint1, &temppoint2);
6273 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6274 weapons[i].rotation2 *= 360 / 6.28;
6277 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6278 weapons[i].rotation1 *= 360 / 6.28;
6279 weapons[i].rotation3 = 0;
6280 weapons[i].smallrotation = 90;
6281 weapons[i].smallrotation2 = 0;
6282 if (temppoint1.x > temppoint2.x)
6283 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6285 if (animTarget == knifethrowanim) {
6286 weapons[i].smallrotation = 90;
6287 //weapons[i].smallrotation2=-90;
6288 weapons[i].smallrotation2 = 0;
6289 weapons[i].rotation1 = 0;
6290 weapons[i].rotation2 = 0;
6291 weapons[i].rotation3 = 0;
6293 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6294 weapons[i].smallrotation = -90;
6295 weapons[i].rotation1 = 0;
6296 weapons[i].rotation2 = 0;
6297 weapons[i].rotation3 = 0;
6300 if (weapons[i].getType() == sword) {
6301 weapons[i].smallrotation = 0;
6302 weapons[i].smallrotation2 = 0;
6303 if (animTarget == knifethrowanim) {
6304 weapons[i].smallrotation = -90;
6305 weapons[i].smallrotation2 = 0;
6306 weapons[i].rotation1 = 0;
6307 weapons[i].rotation2 = 0;
6308 weapons[i].rotation3 = 0;
6310 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)) {
6311 XYZ temppoint1, temppoint2, tempforward;
6314 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6315 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6316 distance = findDistance(&temppoint1, &temppoint2);
6317 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6318 weapons[i].rotation2 *= 360 / 6.28;
6321 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6322 weapons[i].rotation1 *= 360 / 6.28;
6323 weapons[i].rotation3 = 0;
6324 weapons[i].smallrotation = 90;
6325 weapons[i].smallrotation2 = 0;
6326 if (temppoint1.x > temppoint2.x)
6327 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6330 if (weapons[i].getType() == staff) {
6331 weapons[i].smallrotation = 100;
6332 weapons[i].smallrotation2 = 0;
6333 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6334 XYZ temppoint1, temppoint2, tempforward;
6337 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6338 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6339 distance = findDistance(&temppoint1, &temppoint2);
6340 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6341 weapons[i].rotation2 *= 360 / 6.28;
6344 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6345 weapons[i].rotation1 *= 360 / 6.28;
6346 weapons[i].rotation3 = 0;
6347 weapons[i].smallrotation = 90;
6348 weapons[i].smallrotation2 = 0;
6349 if (temppoint1.x > temppoint2.x)
6350 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6354 if (weaponactive != k && weaponstuck != k) {
6355 if (weapons[i].getType() == knife) {
6356 weapons[i].smallrotation = -70;
6357 weapons[i].smallrotation2 = 10;
6359 if (weapons[i].getType() == sword) {
6360 weapons[i].smallrotation = -100;
6361 weapons[i].smallrotation2 = -8;
6363 if (weapons[i].getType() == staff) {
6364 weapons[i].smallrotation = -100;
6365 weapons[i].smallrotation2 = -8;
6368 if (weaponstuck == k) {
6369 if (weaponstuckwhere == 0)
6370 weapons[i].smallrotation = 180;
6372 weapons[i].smallrotation = 0;
6373 weapons[i].smallrotation2 = 10;
6382 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6384 if (animCurrent != animTarget)
6386 if (skeleton.free == 2)
6395 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6398 static float distance;
6399 static float olddistance;
6400 static int intersecting;
6401 static int firstintersecting;
6404 static XYZ start, end;
6405 static float slopethreshold = -.4;
6407 firstintersecting = -1;
6411 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6414 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6415 for (i = 0; i < 4; i++) {
6416 for (j = 0; j < model->TriangleNum; j++) {
6417 if (model->facenormals[j].y <= slopethreshold) {
6419 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)));
6420 if (distance < radius) {
6421 point = *p1 - model->facenormals[j] * distance;
6422 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]]))
6425 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6426 &model->vertex[model->Triangles[j].vertex[1]],
6429 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6430 &model->vertex[model->Triangles[j].vertex[2]],
6433 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6434 &model->vertex[model->Triangles[j].vertex[2]],
6437 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6441 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)) {
6442 p1->y = point.y + radius;
6443 if ((animTarget == jumpdownanim || isFlip())) {
6444 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6447 if (animTarget == jumpupanim) {
6449 animTarget = getIdle();
6456 pause_sound(whooshsound);
6457 OPENAL_SetVolume(channels[whooshsound], 0);
6460 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6463 animTarget = getLanding();
6464 emit_sound_at(landsound, coords, 128.);
6467 envsound[numenvsounds] = coords;
6468 envsoundvol[numenvsounds] = 16;
6469 envsoundlife[numenvsounds] = .4;
6477 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6478 olddistance = distance;
6479 firstintersecting = j;
6484 for (j = 0; j < model->TriangleNum; j++) {
6485 if (model->facenormals[j].y > slopethreshold) {
6488 start.y -= radius / 4;
6489 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6490 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6491 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6492 distance = abs((model->facenormals[j].x * start.x)
6493 + (model->facenormals[j].y * start.y)
6494 + (model->facenormals[j].z * start.z)
6495 - ((model->facenormals[j].x * v0.x)
6496 + (model->facenormals[j].y * v0.y)
6497 + (model->facenormals[j].z * v0.z)));
6498 if (distance < radius * .5) {
6499 point = start - model->facenormals[j] * distance;
6500 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6503 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6505 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6507 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6509 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6510 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6512 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6513 if (findLengthfast(&start) < findLengthfast(&velocity))
6516 *p1 += model->facenormals[j] * (distance - radius * .5);
6519 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6520 olddistance = distance;
6521 firstintersecting = j;
6528 *p = DoRotation(*p, 0, *rotate, 0);
6531 *p1 = DoRotation(*p1, 0, *rotate, 0);
6533 return firstintersecting;
6536 void Person::takeWeapon(int weaponId)
6539 weapons[weaponId].owner = id;
6540 if (num_weapons > 0) {
6541 weaponids[num_weapons] = weaponids[0];
6544 weaponids[0] = weaponId;