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 This file is part of Lugaru.
9 Lugaru is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 Lugaru is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
23 #include "Objects/Weapons.hpp"
25 #include "Animation/Animation.hpp"
26 #include "Audio/openal_wrapper.hpp"
27 #include "Audio/Sounds.hpp"
29 #include "Level/Awards.hpp"
30 #include "Tutorial.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern GLubyte bloodText[512 * 512 * 3];
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
52 extern int numthrowkill;
54 Model Weapon::throwingknifemodel;
55 Texture Weapon::knifetextureptr;
56 Texture Weapon::lightbloodknifetextureptr;
57 Texture Weapon::bloodknifetextureptr;
59 Model Weapon::swordmodel;
60 Texture Weapon::swordtextureptr;
61 Texture Weapon::lightbloodswordtextureptr;
62 Texture Weapon::bloodswordtextureptr;
64 Model Weapon::staffmodel;
65 Texture Weapon::stafftextureptr;
67 Weapon::Weapon(int t, int o) : owner(o)
80 void Weapon::setType(int t)
100 void Weapon::DoStuff(int i)
102 static int whichpatchx, whichpatchz, whichhit;
103 static XYZ start, end, colpoint, normalrot, footvel, footpoint;
104 static XYZ terrainnormal;
107 static XYZ newpoint1, newpoint2;
108 static float friction = 3.5;
109 static float elasticity = .4;
110 static XYZ bounceness;
111 static float frictionness;
112 static float closestdistance;
113 static float distance;
115 static XYZ closestpoint;
116 static XYZ closestswordpoint;
117 static float tempmult;
119 if (multiplier <= 0) {
126 if (damage >= 2 && type == staff && owner != -1) { // the staff breaks
127 emit_sound_at(staffbreaksound, tippoint);
129 for (int j = 0; j < 40; j++) {
130 tempvel.x = float(abs(Random() % 100) - 50) / 20;
131 tempvel.y = float(abs(Random() % 100) - 50) / 20;
132 tempvel.z = float(abs(Random() % 100) - 50) / 20;
133 Sprite::MakeSprite(splintersprite, position + (tippoint - position) * ((float)j - 8) / 32, tempvel * .5, 115 / 255, 73 / 255, 12 / 255, .1, 1);
136 Person::players[owner]->weaponactive = -1;
137 Person::players[owner]->num_weapons--;
138 if (Person::players[owner]->num_weapons) {
139 Person::players[owner]->weaponids[0] = Person::players[owner]->weaponids[Person::players[owner]->num_weapons];
140 if (Person::players[owner]->weaponstuck == Person::players[owner]->num_weapons)
141 Person::players[owner]->weaponstuck = 0;
152 oldposition = position;
153 oldtippoint = tippoint;
154 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && !physics) { // if the weapon is flying
155 position += velocity * multiplier;
156 tippoint += velocity * multiplier;
157 whichpatchx = position.x / (terrain.size / subdivision * terrain.scale);
158 whichpatchz = position.z / (terrain.size / subdivision * terrain.scale);
159 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
160 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) { // if there are Object::objects where the weapon is
161 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) { // check for collision
162 int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
165 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
166 if (whichhit != -1) {
167 if (Object::objects[k]->type == treetrunktype) {
168 Object::objects[k]->model.MakeDecal(breakdecal, DoRotation(colpoint - Object::objects[k]->position, 0, -Object::objects[k]->yaw, 0), .1, 1, Random() % 360);
169 normalrot = DoRotation(Object::objects[k]->model.facenormals[whichhit], 0, Object::objects[k]->yaw, 0);
172 position = colpoint - normalrot * .1;
173 else if (type == sword)
174 position = colpoint - normalrot * .2;
175 else if (type == staff)
176 position = colpoint - normalrot * .2;
177 XYZ temppoint1, temppoint2;
181 temppoint2 = normalrot;
182 distance = findDistance(&temppoint1, &temppoint2);
183 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
184 rotation2 *= 360 / 6.28;
187 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
188 rotation1 *= 360 / 6.28;
189 if (temppoint1.x > temppoint2.x)
190 rotation1 = 360 - rotation1;
199 emit_sound_at(knifesheathesound, position, 128.);
203 Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
207 position -= velocity * multiplier;
208 tippoint -= velocity * multiplier;
209 tipvelocity = velocity;
216 if (velocity.x || velocity.y || velocity.z) {
217 for (unsigned j = 0; j < Person::players.size(); j++) {
219 footpoint = DoRotation((Person::players[j]->jointPos(abdomen) + Person::players[j]->jointPos(neck)) / 2, 0, Person::players[j]->yaw, 0) * Person::players[j]->scale + Person::players[j]->coords;
220 if (owner == -1 && distsqflat(&position, &Person::players[j]->coords) < 1.5 &&
221 distsq(&position, &Person::players[j]->coords) < 4 && Person::players[j]->weaponstuck == -1 &&
222 !Person::players[j]->skeleton.free && (int(j) != oldowner)) {
223 if ((Person::players[j]->aitype != attacktypecutoff || abs(Random() % 6) == 0 || (Person::players[j]->animTarget != backhandspringanim && Person::players[j]->animTarget != rollanim && Person::players[j]->animTarget != flipanim && Random() % 2 == 0)) && !missed) {
224 if ( (Person::players[j]->creature == wolftype && Random() % 3 != 0 && Person::players[j]->weaponactive == -1 && (Person::players[j]->isIdle() || Person::players[j]->isRun() || Person::players[j]->animTarget == walkanim)) ||
225 (Person::players[j]->creature == rabbittype && Random() % 2 == 0 && Person::players[j]->aitype == attacktypecutoff && Person::players[j]->weaponactive == -1)) {
226 emit_sound_at(knifedrawsound, Person::players[j]->coords, 128.);
228 Person::players[j]->animTarget = removeknifeanim;
229 Person::players[j]->frameTarget = 1;
230 Person::players[j]->target = 1;
231 Person::players[j]->takeWeapon(i);
233 Person::players[j]->aitype = attacktypecutoff;
237 Person::players[j]->num_weapons++;
238 Person::players[j]->weaponstuck = Person::players[j]->num_weapons - 1;
239 if (normaldotproduct(Person::players[j]->facing, velocity) > 0)
240 Person::players[j]->weaponstuckwhere = 1;
242 Person::players[j]->weaponstuckwhere = 0;
244 Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
246 Person::players[j]->RagDoll(0);
247 Person::players[j]->jointVel(abdomen) += velocity * 2;
248 Person::players[j]->jointVel(neck) += velocity * 2;
249 Person::players[j]->jointVel(rightshoulder) += velocity * 2;
250 Person::players[j]->jointVel(leftshoulder) += velocity * 2;
251 if (bloodtoggle && !Tutorial::active)
252 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
253 if (Tutorial::active)
254 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
255 footvel = tippoint - position;
257 if (bloodtoggle && !Tutorial::active)
258 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
260 if (!Tutorial::active) {
261 if (Person::players[j]->weaponstuckwhere == 0)
262 Person::players[j]->DoBloodBig(2, 205);
263 if (Person::players[j]->weaponstuckwhere == 1)
264 Person::players[j]->DoBloodBig(2, 200);
265 Person::players[j]->damage += 200 / Person::players[j]->armorhigh;
266 Person::players[j]->deathbleeding = 1;
267 Person::players[j]->bloodloss += (200 + abs((float)(Random() % 40)) - 20) / Person::players[j]->armorhigh;
273 emit_sound_at(fleshstabsound, position, 128.);
275 if (Animation::animations[Person::players[0]->animTarget].height == highheight)
276 award_bonus(0, ninja);
278 award_bonus(0, Bullseyebonus);
286 if (position.y < terrain.getHeight(position.x, position.z)) {
287 if (terrain.getOpacity(position.x, position.z) < .2) {
289 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
290 position = colpoint * terrain.scale;
292 position.y = terrain.getHeight(position.x, position.z);
295 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
296 normalrot = terrain.getNormal(position.x, position.z) * -1;
298 glMatrixMode(GL_MODELVIEW);
302 glRotatef(bigrotation, 0, 1, 0);
303 glRotatef(bigtilt2, 1, 0, 0);
304 glRotatef(bigtilt, 0, 0, 1);
305 glRotatef(-rotation1 + 90, 0, 1, 0);
306 glRotatef(-rotation2 + 90, 0, 0, 1);
307 glRotatef(-rotation3, 0, 1, 0);
308 glRotatef(smallrotation, 1, 0, 0);
309 glRotatef(smallrotation2, 0, 1, 0);
310 glTranslatef(0, 0, 1);
311 glGetFloatv(GL_MODELVIEW_MATRIX, M);
316 position -= tippoint * .15;
317 XYZ temppoint1, temppoint2;
326 emit_sound_at(knifesheathesound, position, 128.);
329 terrainlight = terrain.getLighting(position.x, position.z);
330 if (environment == snowyenvironment) {
331 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
332 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
333 } else if (environment == grassyenvironment) {
334 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
335 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
336 } else if (environment == desertenvironment) {
337 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
338 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
345 position -= velocity * multiplier;
346 tippoint -= velocity * multiplier;
347 tipvelocity = velocity;
350 if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
351 velocity.y += gravity * multiplier;
353 XYZ temppoint1, temppoint2;
357 temppoint2 = velocity;
358 distance = findDistance(&temppoint1, &temppoint2);
359 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
360 rotation2 *= 360 / 6.28;
363 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
364 rotation1 *= 360 / 6.28;
371 if (temppoint1.x > temppoint2.x)
372 rotation1 = 360 - rotation1;
382 tempmult = multiplier;
384 for (int l = 0; l < 10; l++) {
385 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
387 position += velocity * multiplier;
388 tippoint += tipvelocity * multiplier;
391 midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
392 vel = tippoint - midp;
394 newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
395 newpoint2 = midp + vel * length * (mass / (mass + tipmass));
397 if (freetime > .04) {
398 velocity = velocity + (newpoint1 - position) / multiplier;
399 tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
402 position = newpoint1;
403 tippoint = newpoint2;
407 whichpatchx = (position.x) / (terrain.size / subdivision * terrain.scale);
408 whichpatchz = (position.z) / (terrain.size / subdivision * terrain.scale);
409 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision)
410 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) {
411 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
412 int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
416 start = tippoint - (position - tippoint) / 5;
417 end = position + (position - tippoint) / 30;
418 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
419 if (whichhit != -1) {
421 diff = (colpoint - position);
425 tippoint += (colpoint - position) + diff * .05;
426 position = colpoint + diff * .05;
427 oldtippoint = tippoint;
428 oldposition = tippoint;
431 start = position - (tippoint - position) / 5;
432 end = tippoint + (tippoint - position) / 30;
433 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
434 if (whichhit != -1) {
436 diff = (colpoint - tippoint);
440 position += (colpoint - tippoint) + diff * .05;
441 tippoint = colpoint + diff * .05;
442 oldposition = position;
443 oldtippoint = tippoint;
450 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
451 if (whichhit != -1) {
454 terrainnormal = DoRotation(Object::objects[k]->model.facenormals[whichhit], 0, Object::objects[k]->yaw, 0) * -1;
455 ReflectVector(&velocity, &terrainnormal);
456 position += terrainnormal * .002;
458 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
459 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
461 frictionness = abs(normaldotproduct(velocity, terrainnormal));
462 velocity -= bounceness;
463 if (1 - friction * frictionness > 0)
464 velocity *= 1 - friction * frictionness;
467 velocity += bounceness * elasticity;
469 if (findLengthfast(&bounceness) > 1) {
472 whichsound = footstepsound3 + abs(Random() % 2);
474 whichsound = clank1sound + abs(Random() % 4);
475 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
480 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
481 if (whichhit != -1) {
484 terrainnormal = DoRotation(Object::objects[k]->model.facenormals[whichhit], 0, Object::objects[k]->yaw, 0) * -1;
485 ReflectVector(&tipvelocity, &terrainnormal);
486 tippoint += terrainnormal * .002;
488 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
489 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
491 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
492 tipvelocity -= bounceness;
493 if (1 - friction * frictionness > 0)
494 tipvelocity *= 1 - friction * frictionness;
497 tipvelocity += bounceness * elasticity;
499 if (findLengthfast(&bounceness) > 1) {
502 whichsound = footstepsound3 + abs(Random() % 2);
504 whichsound = clank1sound + abs(Random() % 4);
505 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
509 if ((Object::objects[k]->type != boxtype && Object::objects[k]->type != platformtype && Object::objects[k]->type != walltype && Object::objects[k]->type != weirdtype) || Object::objects[k]->pitch != 0)
510 for (int m = 0; m < 2; m++) {
511 mid = (position * (21 + (float)m * 10) + tippoint * (19 - (float)m * 10)) / 40;
513 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
517 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
518 if (whichhit != -1) {
521 terrainnormal = DoRotation(Object::objects[k]->model.facenormals[whichhit], 0, Object::objects[k]->yaw, 0) * -1;
522 ReflectVector(&velocity, &terrainnormal);
524 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
525 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
527 frictionness = abs(normaldotproduct(velocity, terrainnormal));
528 velocity -= bounceness;
529 if (1 - friction * frictionness > 0)
530 velocity *= 1 - friction * frictionness;
533 velocity += bounceness * elasticity;
535 if (findLengthfast(&bounceness) > 1) {
538 whichsound = footstepsound3 + abs(Random() % 2);
540 whichsound = clank1sound + abs(Random() % 4);
541 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
543 position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
546 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
548 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
552 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
553 if (whichhit != -1) {
556 terrainnormal = DoRotation(Object::objects[k]->model.facenormals[whichhit], 0, Object::objects[k]->yaw, 0) * -1;
557 ReflectVector(&tipvelocity, &terrainnormal);
559 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
560 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
562 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
563 tipvelocity -= bounceness;
564 if (1 - friction * frictionness > 0)
565 tipvelocity *= 1 - friction * frictionness;
568 tipvelocity += bounceness * elasticity;
570 if (findLengthfast(&bounceness) > 1) {
573 whichsound = footstepsound3 + abs(Random() % 2);
575 whichsound = clank1sound + abs(Random() % 4);
576 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
578 tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
584 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
585 if (whichhit != -1) {
587 closestdistance = -1;
588 closestswordpoint = colpoint; //(position+tippoint)/2;
589 point[0] = DoRotation(Object::objects[k]->model.vertex[Object::objects[k]->model.Triangles[whichhit].vertex[0]], 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
590 point[1] = DoRotation(Object::objects[k]->model.vertex[Object::objects[k]->model.Triangles[whichhit].vertex[1]], 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
591 point[2] = DoRotation(Object::objects[k]->model.vertex[Object::objects[k]->model.Triangles[whichhit].vertex[2]], 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
592 if (DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance, &colpoint )) {
593 if (distance < closestdistance || closestdistance == -1) {
594 closestpoint = colpoint;
595 closestdistance = distance;
598 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint )) {
599 if (distance < closestdistance || closestdistance == -1) {
600 closestpoint = colpoint;
601 closestdistance = distance;
604 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint )) {
605 if (distance < closestdistance || closestdistance == -1) {
606 closestpoint = colpoint;
607 closestdistance = distance;
610 if (closestdistance != -1 && isnormal(closestdistance)) {
611 if (DistancePointLine(&closestpoint, &position, &tippoint, &distance, &colpoint )) {
612 closestswordpoint = colpoint;
613 velocity += (closestpoint - closestswordpoint);
614 tipvelocity += (closestpoint - closestswordpoint);
615 position += (closestpoint - closestswordpoint);
616 tippoint += (closestpoint - closestswordpoint);
624 whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
625 if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
628 position = colpoint * terrain.scale;
630 position.y = terrain.getHeight(position.x, position.z);
632 terrainnormal = terrain.getNormal(position.x, position.z);
633 ReflectVector(&velocity, &terrainnormal);
634 position += terrainnormal * .002;
635 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
636 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
638 frictionness = abs(normaldotproduct(velocity, terrainnormal));
639 velocity -= bounceness;
640 if (1 - friction * frictionness > 0)
641 velocity *= 1 - friction * frictionness;
644 if (terrain.getOpacity(position.x, position.z) < .2)
645 velocity += bounceness * elasticity * .3;
647 velocity += bounceness * elasticity;
649 if (findLengthfast(&bounceness) > 1) {
651 if (terrain.getOpacity(position.x, position.z) > .2) {
653 whichsound = footstepsound3 + abs(Random() % 2);
655 whichsound = clank1sound + abs(Random() % 4);
657 whichsound = footstepsound + abs(Random() % 2);
659 emit_sound_at(whichsound, position,
660 findLengthfast(&bounceness)
661 * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
663 if (terrain.getOpacity(position.x, position.z) < .2) {
665 terrainlight = terrain.getLighting(position.x, position.z);
666 if (environment == snowyenvironment) {
667 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
668 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
669 } else if (environment == grassyenvironment) {
670 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
671 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
672 } else if (environment == desertenvironment) {
673 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
674 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
679 whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
680 if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
682 tippoint = colpoint * terrain.scale;
684 tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
686 terrainnormal = terrain.getNormal(tippoint.x, tippoint.z);
687 ReflectVector(&tipvelocity, &terrainnormal);
688 tippoint += terrainnormal * .002;
689 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
690 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
692 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
693 tipvelocity -= bounceness;
694 if (1 - friction * frictionness > 0)
695 tipvelocity *= 1 - friction * frictionness;
698 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2)
699 tipvelocity += bounceness * elasticity * .3;
701 tipvelocity += bounceness * elasticity;
703 if (findLengthfast(&bounceness) > 1) {
705 if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
707 whichsound = footstepsound3 + abs(Random() % 2);
709 whichsound = clank1sound + abs(Random() % 4);
711 whichsound = footstepsound + abs(Random() % 2);
713 emit_sound_at(whichsound, tippoint,
714 findLengthfast(&bounceness)
715 * (terrain.getOpacity(tippoint.x, tippoint.z) > .2 ? 128. : 32.));
717 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
719 terrainlight = terrain.getLighting(tippoint.x, tippoint.z);
720 if (environment == snowyenvironment) {
721 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
722 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
723 } else if (environment == grassyenvironment) {
724 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
725 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
726 } else if (environment == desertenvironment) {
727 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
728 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
735 mid = position + tippoint;
737 mid += (position - mid) / 20;
739 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
741 mid.y = terrain.getHeight(mid.x, mid.z);
743 terrainnormal = terrain.getNormal(mid.x, mid.z);
744 ReflectVector(&velocity, &terrainnormal);
745 //mid+=terrainnormal*.002;
746 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
747 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
749 frictionness = abs(normaldotproduct(velocity, terrainnormal));
750 velocity -= bounceness;
751 if (1 - friction * frictionness > 0)
752 velocity *= 1 - friction * frictionness;
755 if (terrain.getOpacity(mid.x, mid.z) < .2)
756 velocity += bounceness * elasticity * .3;
758 velocity += bounceness * elasticity;
760 if (findLengthfast(&bounceness) > 1) {
762 if (terrain.getOpacity(mid.x, mid.z) > .2) {
764 whichsound = footstepsound3 + abs(Random() % 2);
766 whichsound = clank1sound + abs(Random() % 4);
768 whichsound = footstepsound + abs(Random() % 2);
770 emit_sound_at(whichsound, mid,
771 findLengthfast(&bounceness)
772 * (terrain.getOpacity(position.x, position.z) > .2
776 position += (mid - oldmid) * 20;
779 mid = position + tippoint;
781 mid += (tippoint - mid) / 20;
783 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
785 mid.y = terrain.getHeight(mid.x, mid.z);
787 terrainnormal = terrain.getNormal(mid.x, mid.z);
788 ReflectVector(&tipvelocity, &terrainnormal);
789 //mid+=terrainnormal*.002;
790 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
791 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
793 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
794 tipvelocity -= bounceness;
795 if (1 - friction * frictionness > 0)
796 tipvelocity *= 1 - friction * frictionness;
799 if (terrain.getOpacity(mid.x, mid.z) < .2)
800 tipvelocity += bounceness * elasticity * .3;
802 tipvelocity += bounceness * elasticity;
804 if (findLengthfast(&bounceness) > 1) {
806 if (terrain.getOpacity(mid.x, mid.z) > .2) {
808 whichsound = footstepsound3 + abs(Random() % 2);
810 whichsound = clank1sound + abs(Random() % 4);
812 whichsound = footstepsound + abs(Random() % 2);
814 emit_sound_at(whichsound, mid,
815 findLengthfast(&bounceness)
816 * (terrain.getOpacity(position.x, position.z) > .2
820 tippoint += (mid - oldmid) * 20;
823 velocity.y += gravity * multiplier;
824 tipvelocity.y += gravity * multiplier;
827 XYZ temppoint1, temppoint2;
830 temppoint1 = position;
831 temppoint2 = tippoint;
832 distance = findDistance(&temppoint1, &temppoint2);
833 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
834 rotation2 *= 360 / 6.28;
837 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
838 rotation1 *= 360 / 6.28;
845 if (temppoint1.x > temppoint2.x)
846 rotation1 = 360 - rotation1;
849 if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
850 freetime += multiplier;
860 multiplier = tempmult;
861 if (blooddrip && bloody) {
862 blooddripdelay -= blooddrip * multiplier / 2;
863 blooddrip -= multiplier;
868 if (blooddripdelay < 0 && bloodtoggle) {
872 bloodloc = position + (tippoint - position) * .7;
876 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
881 flamedelay -= multiplier;
882 if (onfire && flamedelay <= 0) {
884 flamedelay -= multiplier;
887 normalrot = Person::players[owner]->velocity;
891 if (Person::players[owner]->onterrain) {
895 Sprite::MakeSprite(weaponflamesprite, position + tippoint * (((float)abs(Random() % 100)) / 600 + .05), normalrot, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3, 1);
896 Sprite::setLastSpriteSpeed(4);
897 Sprite::setLastSpriteAlivetime(.3);
901 if (!onfire && owner == -1 && type != staff) {
902 flamedelay -= multiplier;
903 if (flamedelay <= 0) {
905 flamedelay -= multiplier;
907 if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
909 shinepoint = position + (tippoint - position) * (((float)abs(Random() % 100)) / 100);
910 Sprite::MakeSprite(weaponshinesprite, shinepoint, normalrot, 1, 1, 1, (.1 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3 * fast_sqrt(findDistance(&shinepoint, &viewer)), 1);
911 Sprite::setLastSpriteSpeed(4);
912 Sprite::setLastSpriteAlivetime(.3);
918 void Weapons::DoStuff()
922 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
923 weapon->DoStuff(i++);
929 static XYZ terrainlight;
930 static GLfloat M[16];
932 if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
933 distsq(&viewer, &position) < viewdistance * viewdistance)) {
937 if (velocity.x && !physics)
942 if (Person::players[owner]->occluded < 25)
943 if ((frustum.SphereInFrustum(Person::players[owner]->coords.x, Person::players[owner]->coords.y + Person::players[owner]->scale * 3, Person::players[owner]->coords.z, Person::players[owner]->scale * 8) && distsq(&viewer, &Person::players[owner]->coords) < viewdistance * viewdistance) || Person::players[owner]->skeleton.free == 3)
946 (Person::players[owner]->animTarget == knifeslashstartanim ||
947 Person::players[owner]->animTarget == swordsneakattackanim ||
948 (Person::players[owner]->animCurrent == staffhitanim && Person::players[owner]->frameCurrent > 1) ||
949 (Person::players[owner]->animCurrent == staffhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
950 (Person::players[owner]->animCurrent == staffspinhitanim && Person::players[owner]->frameCurrent > 1) ||
951 (Person::players[owner]->animCurrent == staffspinhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
952 (Person::players[owner]->animCurrent == staffgroundsmashanim && Person::players[owner]->frameCurrent > 1) ||
953 (Person::players[owner]->animTarget == swordslashanim && Person::players[owner]->frameTarget < 7) ||
954 Person::players[owner]->animTarget == crouchstabanim ||
955 Person::players[owner]->animTarget == swordslashreversalanim ||
956 Person::players[owner]->animTarget == swordslashreversedanim ||
957 Person::players[owner]->animTarget == knifefollowanim ||
958 Person::players[owner]->animTarget == swordgroundstabanim ||
959 Person::players[owner]->animTarget == knifethrowanim) &&
960 Person::players[owner]->animTarget == lastdrawnanim &&
961 !Person::players[owner]->skeleton.free
967 if (Person::players[owner]->animTarget == swordgroundstabanim) {
968 lastdrawnrotation1 = rotation1;
969 lastdrawnrotation2 = rotation2;
970 lastdrawnrotation3 = rotation3;
971 lastdrawnbigrotation = bigrotation;
972 lastdrawnbigtilt = bigtilt;
973 lastdrawnbigtilt2 = bigtilt2;
974 lastdrawnsmallrotation = smallrotation;
975 lastdrawnsmallrotation2 = smallrotation2;
979 terrainlight = terrain.getLighting(position.x, position.z);
980 if (drawhowmany > 0) {
981 glAlphaFunc(GL_GREATER, 0.01);
983 for (int j = drawhowmany; j > 0; j--) {
984 glMatrixMode(GL_MODELVIEW);
986 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
988 glTranslatef(position.x * (((float)(j)) / drawhowmany) + lastdrawnposition.x * (1 - ((float)(j)) / drawhowmany), position.y * (((float)(j)) / drawhowmany) + lastdrawnposition.y * (1 - ((float)(j)) / drawhowmany), position.z * (((float)(j)) / drawhowmany) + lastdrawnposition.z * (1 - ((float)(j)) / drawhowmany));
990 glTranslatef(position.x * (((float)(j)) / drawhowmany) + lastdrawnposition.x * (1 - ((float)(j)) / drawhowmany), position.y * (((float)(j)) / drawhowmany) - .02 + lastdrawnposition.y * (1 - ((float)(j)) / drawhowmany), position.z * (((float)(j)) / drawhowmany) + lastdrawnposition.z * (1 - ((float)(j)) / drawhowmany));
991 glRotatef(bigrotation * (((float)(j)) / drawhowmany) + lastdrawnbigrotation * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
992 glRotatef(bigtilt2 * (((float)(j)) / drawhowmany) + lastdrawnbigtilt2 * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
993 glRotatef(bigtilt * (((float)(j)) / drawhowmany) + lastdrawnbigtilt * (1 - ((float)(j)) / drawhowmany), 0, 0, 1);
994 glRotatef(-rotation1 * (((float)(j)) / drawhowmany) - lastdrawnrotation1 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 1, 0);
995 glRotatef(-rotation2 * (((float)(j)) / drawhowmany) - lastdrawnrotation2 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 0, 1);
996 glRotatef(-rotation3 * (((float)(j)) / drawhowmany) - lastdrawnrotation3 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
997 glRotatef(smallrotation * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
998 glRotatef(smallrotation2 * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation2 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1001 if (Person::players[owner]->animTarget == staffhitanim || Person::players[owner]->animCurrent == staffhitanim || Person::players[owner]->animTarget == staffhitreversedanim || Person::players[owner]->animCurrent == staffhitreversedanim) {
1002 glTranslatef(0, 0, -.3);
1004 if (Person::players[owner]->animTarget == staffgroundsmashanim || Person::players[owner]->animCurrent == staffgroundsmashanim || Person::players[owner]->animTarget == staffspinhitreversedanim || Person::players[owner]->animCurrent == staffspinhitreversedanim || Person::players[owner]->animTarget == staffspinhitanim || Person::players[owner]->animCurrent == staffspinhitanim) {
1005 glTranslatef(0, 0, -.1);
1009 glEnable(GL_LIGHTING);
1012 if (!bloody || !bloodtoggle)
1013 throwingknifemodel.drawdifftex(knifetextureptr);
1016 throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1018 throwingknifemodel.drawdifftex(bloodknifetextureptr);
1022 if (!bloody || !bloodtoggle)
1023 swordmodel.drawdifftex(swordtextureptr);
1026 swordmodel.drawdifftex(lightbloodswordtextureptr);
1028 swordmodel.drawdifftex(bloodswordtextureptr);
1032 staffmodel.drawdifftex(stafftextureptr);
1039 lastdrawnposition = position;
1040 lastdrawntippoint = tippoint;
1041 lastdrawnrotation1 = rotation1;
1042 lastdrawnrotation2 = rotation2;
1043 lastdrawnrotation3 = rotation3;
1044 lastdrawnbigrotation = bigrotation;
1045 lastdrawnbigtilt = bigtilt;
1046 lastdrawnbigtilt2 = bigtilt2;
1047 lastdrawnsmallrotation = smallrotation;
1048 lastdrawnsmallrotation2 = smallrotation2;
1050 lastdrawnanim = Person::players[owner]->animCurrent;
1053 glMatrixMode(GL_MODELVIEW);
1056 glTranslatef(position.x, position.y - .02, position.z);
1057 glRotatef(bigrotation, 0, 1, 0);
1058 glRotatef(bigtilt2, 1, 0, 0);
1059 glRotatef(bigtilt, 0, 0, 1);
1060 glRotatef(-rotation1 + 90, 0, 1, 0);
1061 glRotatef(-rotation2 + 90, 0, 0, 1);
1062 glRotatef(-rotation3, 0, 1, 0);
1063 glRotatef(smallrotation, 1, 0, 0);
1064 glRotatef(smallrotation2, 0, 1, 0);
1065 glTranslatef(0, 0, length);
1066 glGetFloatv(GL_MODELVIEW_MATRIX, M);
1075 void Weapon::drop(XYZ v, XYZ tv, bool sethitsomething)
1081 if (sethitsomething) {
1089 void Weapon::thrown(XYZ v, bool sethitsomething)
1091 drop(v, v, sethitsomething);
1098 glAlphaFunc(GL_GREATER, 0.9);
1099 glEnable(GL_TEXTURE_2D);
1101 glEnable(GL_CULL_FACE);
1102 glCullFace(GL_FRONT);
1105 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {