2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - 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/Sounds.hpp"
27 #include "Audio/openal_wrapper.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 int bloodtoggle;
45 extern bool autoslomo;
46 extern float camerashake;
48 extern float viewdistance;
49 extern float blackout;
51 extern int numthrowkill;
53 Model Weapon::throwingknifemodel;
54 Texture Weapon::knifetextureptr;
55 Texture Weapon::lightbloodknifetextureptr;
56 Texture Weapon::bloodknifetextureptr;
58 Model Weapon::swordmodel;
59 Texture Weapon::swordtextureptr;
60 Texture Weapon::lightbloodswordtextureptr;
61 Texture Weapon::bloodswordtextureptr;
63 Model Weapon::staffmodel;
64 Texture Weapon::stafftextureptr;
66 Weapon::Weapon(int t, int o)
80 void Weapon::setType(int t)
100 /* Load weapons models and textures */
103 LOG("Loading weapon data...");
105 knifetextureptr.load("Textures/Knife.png", 0);
106 bloodknifetextureptr.load("Textures/BloodKnife.png", 0);
107 lightbloodknifetextureptr.load("Textures/BloodKnifeLight.png", 0);
108 swordtextureptr.load("Textures/Sword.jpg", 1);
109 bloodswordtextureptr.load("Textures/SwordBlood.jpg", 1);
110 lightbloodswordtextureptr.load("Textures/SwordBloodLight.jpg", 1);
111 stafftextureptr.load("Textures/Staff.jpg", 1);
113 throwingknifemodel.load("Models/ThrowingKnife.solid");
114 throwingknifemodel.Scale(.001, .001, .001);
115 throwingknifemodel.Rotate(90, 0, 0);
116 throwingknifemodel.Rotate(0, 90, 0);
117 throwingknifemodel.flat = 0;
118 throwingknifemodel.CalculateNormals(1);
120 swordmodel.load("Models/Sword.solid");
121 swordmodel.Scale(.001, .001, .001);
122 swordmodel.Rotate(90, 0, 0);
123 swordmodel.Rotate(0, 90, 0);
124 swordmodel.Rotate(0, 0, 90);
126 swordmodel.CalculateNormals(1);
128 staffmodel.load("Models/Staff.solid");
129 staffmodel.Scale(.005, .005, .005);
130 staffmodel.Rotate(90, 0, 0);
131 staffmodel.Rotate(0, 90, 0);
132 staffmodel.Rotate(0, 0, 90);
134 staffmodel.CalculateNormals(1);
137 void Weapon::doStuff(int i)
139 static int whichpatchx, whichpatchz, whichhit;
140 static XYZ start, end, colpoint, normalrot, footvel, footpoint;
141 static XYZ terrainnormal;
144 static XYZ newpoint1, newpoint2;
145 static float friction = 3.5;
146 static float elasticity = .4;
147 static XYZ bounceness;
148 static float frictionness;
149 static float closestdistance;
150 static float distance;
152 static XYZ closestpoint;
153 static XYZ closestswordpoint;
154 static float tempmult;
156 if (multiplier <= 0) {
163 if (damage >= 2 && type == staff && owner != -1) { // the staff breaks
164 emit_sound_at(staffbreaksound, tippoint);
166 for (int j = 0; j < 40; j++) {
167 tempvel.x = float(abs(Random() % 100) - 50) / 20;
168 tempvel.y = float(abs(Random() % 100) - 50) / 20;
169 tempvel.z = float(abs(Random() % 100) - 50) / 20;
170 Sprite::MakeSprite(splintersprite, position + (tippoint - position) * ((float)j - 8) / 32, tempvel * .5, 115 / 255, 73 / 255, 12 / 255, .1, 1);
173 Person::players[owner]->weaponactive = -1;
174 Person::players[owner]->num_weapons--;
175 if (Person::players[owner]->num_weapons) {
176 Person::players[owner]->weaponids[0] = Person::players[owner]->weaponids[Person::players[owner]->num_weapons];
177 if (Person::players[owner]->weaponstuck == Person::players[owner]->num_weapons) {
178 Person::players[owner]->weaponstuck = 0;
190 oldposition = position;
191 oldtippoint = tippoint;
192 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && !physics) { // if the weapon is flying
193 position += velocity * multiplier;
194 tippoint += velocity * multiplier;
195 whichpatchx = position.x / (terrain.size / subdivision * terrain.scale);
196 whichpatchz = position.z / (terrain.size / subdivision * terrain.scale);
197 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
198 for (unsigned int j = 0; j < terrain.patchobjects[whichpatchx][whichpatchz].size(); j++) { // check for collision
199 unsigned int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
202 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
203 if (whichhit != -1) {
204 if (Object::objects[k]->type == treetrunktype) {
205 Object::objects[k]->model.MakeDecal(breakdecal, DoRotation(colpoint - Object::objects[k]->position, 0, -Object::objects[k]->yaw, 0), .1, 1, Random() % 360);
206 normalrot = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0);
209 position = colpoint - normalrot * .1;
210 } else if (type == sword) {
211 position = colpoint - normalrot * .2;
212 } else if (type == staff) {
213 position = colpoint - normalrot * .2;
215 XYZ temppoint1, temppoint2;
219 temppoint2 = normalrot;
220 distance = findDistance(&temppoint1, &temppoint2);
221 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
222 rotation2 *= 360 / 6.28;
225 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
226 rotation1 *= 360 / 6.28;
227 if (temppoint1.x > temppoint2.x) {
228 rotation1 = 360 - rotation1;
238 emit_sound_at(knifesheathesound, position, 128.);
242 Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
246 position -= velocity * multiplier;
247 tippoint -= velocity * multiplier;
248 tipvelocity = velocity;
254 if (velocity.x || velocity.y || velocity.z) {
255 for (unsigned j = 0; j < Person::players.size(); j++) {
257 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;
258 if (owner == -1 && distsqflat(&position, &Person::players[j]->coords) < 1.5 &&
259 distsq(&position, &Person::players[j]->coords) < 4 && Person::players[j]->weaponstuck == -1 &&
260 !Person::players[j]->skeleton.free && (int(j) != oldowner)) {
261 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) {
262 if (Person::players[j]->catchKnife()) {
263 emit_sound_at(knifedrawsound, Person::players[j]->coords, 128.);
265 Person::players[j]->animTarget = removeknifeanim;
266 Person::players[j]->frameTarget = 1;
267 Person::players[j]->target = 1;
268 Person::players[j]->takeWeapon(i);
270 Person::players[j]->aitype = attacktypecutoff;
275 Person::players[j]->num_weapons++;
276 Person::players[j]->weaponstuck = Person::players[j]->num_weapons - 1;
277 if (normaldotproduct(Person::players[j]->facing, velocity) > 0) {
278 Person::players[j]->weaponstuckwhere = 1;
280 Person::players[j]->weaponstuckwhere = 0;
283 Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
285 Person::players[j]->RagDoll(0);
286 Person::players[j]->jointVel(abdomen) += velocity * 2;
287 Person::players[j]->jointVel(neck) += velocity * 2;
288 Person::players[j]->jointVel(rightshoulder) += velocity * 2;
289 Person::players[j]->jointVel(leftshoulder) += velocity * 2;
290 if (bloodtoggle && !Tutorial::active) {
291 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
293 if (Tutorial::active) {
294 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
296 footvel = tippoint - position;
298 if (bloodtoggle && !Tutorial::active) {
299 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
302 if (!Tutorial::active) {
303 if (Person::players[j]->weaponstuckwhere == 0) {
304 Person::players[j]->DoBloodBig(2, 205);
306 if (Person::players[j]->weaponstuckwhere == 1) {
307 Person::players[j]->DoBloodBig(2, 200);
309 Person::players[j]->damage += 200 / Person::players[j]->armorhigh;
310 Person::players[j]->deathbleeding = 1;
311 Person::players[j]->bloodloss += (200 + abs((float)(Random() % 40)) - 20) / Person::players[j]->armorhigh;
317 emit_sound_at(fleshstabsound, position, 128.);
319 if (Animation::animations[Person::players[0]->animTarget].height == highheight) {
320 award_bonus(0, ninja);
322 award_bonus(0, Bullseyebonus);
331 if (position.y < terrain.getHeight(position.x, position.z)) {
332 if (terrain.getOpacity(position.x, position.z) < .2) {
334 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
335 position = colpoint * terrain.scale;
337 position.y = terrain.getHeight(position.x, position.z);
340 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
341 normalrot = terrain.getNormal(position.x, position.z) * -1;
343 glMatrixMode(GL_MODELVIEW);
347 glRotatef(bigrotation, 0, 1, 0);
348 glRotatef(bigtilt2, 1, 0, 0);
349 glRotatef(bigtilt, 0, 0, 1);
350 glRotatef(-rotation1 + 90, 0, 1, 0);
351 glRotatef(-rotation2 + 90, 0, 0, 1);
352 glRotatef(-rotation3, 0, 1, 0);
353 glRotatef(smallrotation, 1, 0, 0);
354 glRotatef(smallrotation2, 0, 1, 0);
355 glTranslatef(0, 0, 1);
356 glGetFloatv(GL_MODELVIEW_MATRIX, M);
361 position -= tippoint * .15;
362 XYZ temppoint1, temppoint2;
371 emit_sound_at(knifesheathesound, position, 128.);
374 terrainlight = terrain.getLighting(position.x, position.z);
375 if (environment == snowyenvironment) {
376 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
377 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
379 } else if (environment == grassyenvironment) {
380 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
381 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
383 } else if (environment == desertenvironment) {
384 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
385 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
393 position -= velocity * multiplier;
394 tippoint -= velocity * multiplier;
395 tipvelocity = velocity;
398 if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
399 velocity.y += gravity * multiplier;
401 XYZ temppoint1, temppoint2;
405 temppoint2 = velocity;
406 distance = findDistance(&temppoint1, &temppoint2);
407 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
408 rotation2 *= 360 / 6.28;
411 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
412 rotation1 *= 360 / 6.28;
419 if (temppoint1.x > temppoint2.x) {
420 rotation1 = 360 - rotation1;
430 tempmult = multiplier;
432 for (int l = 0; l < 10; l++) {
433 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
435 position += velocity * multiplier;
436 tippoint += tipvelocity * multiplier;
439 midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
440 vel = tippoint - midp;
442 newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
443 newpoint2 = midp + vel * length * (mass / (mass + tipmass));
445 if (freetime > .04) {
446 velocity = velocity + (newpoint1 - position) / multiplier;
447 tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
450 position = newpoint1;
451 tippoint = newpoint2;
454 whichpatchx = (position.x) / (terrain.size / subdivision * terrain.scale);
455 whichpatchz = (position.z) / (terrain.size / subdivision * terrain.scale);
456 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
457 for (unsigned int j = 0; j < terrain.patchobjects[whichpatchx][whichpatchz].size(); j++) {
458 unsigned int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
462 start = tippoint - (position - tippoint) / 5;
463 end = position + (position - tippoint) / 30;
464 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
465 if (whichhit != -1) {
467 diff = (colpoint - position);
471 tippoint += (colpoint - position) + diff * .05;
472 position = colpoint + diff * .05;
473 oldtippoint = tippoint;
474 oldposition = tippoint;
477 start = position - (tippoint - position) / 5;
478 end = tippoint + (tippoint - position) / 30;
479 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
480 if (whichhit != -1) {
482 diff = (colpoint - tippoint);
486 position += (colpoint - tippoint) + diff * .05;
487 tippoint = colpoint + diff * .05;
488 oldposition = position;
489 oldtippoint = tippoint;
496 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
497 if (whichhit != -1) {
500 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
501 ReflectVector(&velocity, &terrainnormal);
502 position += terrainnormal * .002;
504 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
505 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
508 frictionness = abs(normaldotproduct(velocity, terrainnormal));
509 velocity -= bounceness;
510 if (1 - friction * frictionness > 0) {
511 velocity *= 1 - friction * frictionness;
515 velocity += bounceness * elasticity;
517 if (findLengthfast(&bounceness) > 1) {
520 whichsound = footstepsound3 + abs(Random() % 2);
522 whichsound = clank1sound + abs(Random() % 4);
524 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
529 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
530 if (whichhit != -1) {
533 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
534 ReflectVector(&tipvelocity, &terrainnormal);
535 tippoint += terrainnormal * .002;
537 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
538 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
541 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
542 tipvelocity -= bounceness;
543 if (1 - friction * frictionness > 0) {
544 tipvelocity *= 1 - friction * frictionness;
548 tipvelocity += bounceness * elasticity;
550 if (findLengthfast(&bounceness) > 1) {
553 whichsound = footstepsound3 + abs(Random() % 2);
555 whichsound = clank1sound + abs(Random() % 4);
557 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
561 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) {
562 for (int m = 0; m < 2; m++) {
563 mid = (position * (21 + (float)m * 10) + tippoint * (19 - (float)m * 10)) / 40;
565 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
569 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
570 if (whichhit != -1) {
573 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
574 ReflectVector(&velocity, &terrainnormal);
576 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
577 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
580 frictionness = abs(normaldotproduct(velocity, terrainnormal));
581 velocity -= bounceness;
582 if (1 - friction * frictionness > 0) {
583 velocity *= 1 - friction * frictionness;
587 velocity += bounceness * elasticity;
589 if (findLengthfast(&bounceness) > 1) {
592 whichsound = footstepsound3 + abs(Random() % 2);
594 whichsound = clank1sound + abs(Random() % 4);
596 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
598 position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
601 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
603 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
607 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
608 if (whichhit != -1) {
611 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
612 ReflectVector(&tipvelocity, &terrainnormal);
614 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
615 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
618 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
619 tipvelocity -= bounceness;
620 if (1 - friction * frictionness > 0) {
621 tipvelocity *= 1 - friction * frictionness;
625 tipvelocity += bounceness * elasticity;
627 if (findLengthfast(&bounceness) > 1) {
630 whichsound = footstepsound3 + abs(Random() % 2);
632 whichsound = clank1sound + abs(Random() % 4);
634 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
636 tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
642 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
643 if (whichhit != -1) {
645 closestdistance = -1;
646 closestswordpoint = colpoint;
647 point[0] = DoRotation(Object::objects[k]->model.getTriangleVertex(whichhit, 0), 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
648 point[1] = DoRotation(Object::objects[k]->model.getTriangleVertex(whichhit, 1), 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
649 point[2] = DoRotation(Object::objects[k]->model.getTriangleVertex(whichhit, 2), 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
650 if (DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance, &colpoint)) {
651 if (distance < closestdistance || closestdistance == -1) {
652 closestpoint = colpoint;
653 closestdistance = distance;
656 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint)) {
657 if (distance < closestdistance || closestdistance == -1) {
658 closestpoint = colpoint;
659 closestdistance = distance;
662 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint)) {
663 if (distance < closestdistance || closestdistance == -1) {
664 closestpoint = colpoint;
665 closestdistance = distance;
668 if (closestdistance != -1 && isnormal(closestdistance)) {
669 if (DistancePointLine(&closestpoint, &position, &tippoint, &distance, &colpoint)) {
670 closestswordpoint = colpoint;
671 velocity += (closestpoint - closestswordpoint);
672 tipvelocity += (closestpoint - closestswordpoint);
673 position += (closestpoint - closestswordpoint);
674 tippoint += (closestpoint - closestswordpoint);
682 whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
683 if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
685 if (whichhit != -1) {
686 position = colpoint * terrain.scale;
688 position.y = terrain.getHeight(position.x, position.z);
691 terrainnormal = terrain.getNormal(position.x, position.z);
692 ReflectVector(&velocity, &terrainnormal);
693 position += terrainnormal * .002;
694 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
695 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
698 frictionness = abs(normaldotproduct(velocity, terrainnormal));
699 velocity -= bounceness;
700 if (1 - friction * frictionness > 0) {
701 velocity *= 1 - friction * frictionness;
705 if (terrain.getOpacity(position.x, position.z) < .2) {
706 velocity += bounceness * elasticity * .3;
708 velocity += bounceness * elasticity;
711 if (findLengthfast(&bounceness) > 1) {
713 if (terrain.getOpacity(position.x, position.z) > .2) {
715 whichsound = footstepsound3 + abs(Random() % 2);
717 whichsound = clank1sound + abs(Random() % 4);
720 whichsound = footstepsound + abs(Random() % 2);
722 emit_sound_at(whichsound, position,
723 findLengthfast(&bounceness) * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
725 if (terrain.getOpacity(position.x, position.z) < .2) {
727 terrainlight = terrain.getLighting(position.x, position.z);
728 if (environment == snowyenvironment) {
729 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
730 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
732 } else if (environment == grassyenvironment) {
733 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
734 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
736 } else if (environment == desertenvironment) {
737 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
738 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
744 whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
745 if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
746 if (whichhit != -1) {
747 tippoint = colpoint * terrain.scale;
749 tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
752 terrainnormal = terrain.getNormal(tippoint.x, tippoint.z);
753 ReflectVector(&tipvelocity, &terrainnormal);
754 tippoint += terrainnormal * .002;
755 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
756 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
759 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
760 tipvelocity -= bounceness;
761 if (1 - friction * frictionness > 0) {
762 tipvelocity *= 1 - friction * frictionness;
766 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
767 tipvelocity += bounceness * elasticity * .3;
769 tipvelocity += bounceness * elasticity;
772 if (findLengthfast(&bounceness) > 1) {
774 if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
776 whichsound = footstepsound3 + abs(Random() % 2);
778 whichsound = clank1sound + abs(Random() % 4);
781 whichsound = footstepsound + abs(Random() % 2);
783 emit_sound_at(whichsound, tippoint,
784 findLengthfast(&bounceness) * (terrain.getOpacity(tippoint.x, tippoint.z) > .2 ? 128. : 32.));
786 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
788 terrainlight = terrain.getLighting(tippoint.x, tippoint.z);
789 if (environment == snowyenvironment) {
790 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4) {
791 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
793 } else if (environment == grassyenvironment) {
794 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4) {
795 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
797 } else if (environment == desertenvironment) {
798 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4) {
799 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
807 mid = position + tippoint;
809 mid += (position - mid) / 20;
811 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
813 mid.y = terrain.getHeight(mid.x, mid.z);
815 terrainnormal = terrain.getNormal(mid.x, mid.z);
816 ReflectVector(&velocity, &terrainnormal);
817 //mid+=terrainnormal*.002;
818 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
819 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
822 frictionness = abs(normaldotproduct(velocity, terrainnormal));
823 velocity -= bounceness;
824 if (1 - friction * frictionness > 0) {
825 velocity *= 1 - friction * frictionness;
829 if (terrain.getOpacity(mid.x, mid.z) < .2) {
830 velocity += bounceness * elasticity * .3;
832 velocity += bounceness * elasticity;
835 if (findLengthfast(&bounceness) > 1) {
837 if (terrain.getOpacity(mid.x, mid.z) > .2) {
839 whichsound = footstepsound3 + abs(Random() % 2);
842 whichsound = clank1sound + abs(Random() % 4);
845 whichsound = footstepsound + abs(Random() % 2);
847 emit_sound_at(whichsound, mid,
848 findLengthfast(&bounceness) * (terrain.getOpacity(position.x, position.z) > .2
852 position += (mid - oldmid) * 20;
855 mid = position + tippoint;
857 mid += (tippoint - mid) / 20;
859 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
861 mid.y = terrain.getHeight(mid.x, mid.z);
863 terrainnormal = terrain.getNormal(mid.x, mid.z);
864 ReflectVector(&tipvelocity, &terrainnormal);
865 //mid+=terrainnormal*.002;
866 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
867 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
870 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
871 tipvelocity -= bounceness;
872 if (1 - friction * frictionness > 0) {
873 tipvelocity *= 1 - friction * frictionness;
877 if (terrain.getOpacity(mid.x, mid.z) < .2) {
878 tipvelocity += bounceness * elasticity * .3;
880 tipvelocity += bounceness * elasticity;
883 if (findLengthfast(&bounceness) > 1) {
885 if (terrain.getOpacity(mid.x, mid.z) > .2) {
887 whichsound = footstepsound3 + abs(Random() % 2);
890 whichsound = clank1sound + abs(Random() % 4);
893 whichsound = footstepsound + abs(Random() % 2);
895 emit_sound_at(whichsound, mid,
896 findLengthfast(&bounceness) * (terrain.getOpacity(position.x, position.z) > .2
900 tippoint += (mid - oldmid) * 20;
903 velocity.y += gravity * multiplier;
904 tipvelocity.y += gravity * multiplier;
907 XYZ temppoint1, temppoint2;
910 temppoint1 = position;
911 temppoint2 = tippoint;
912 distance = findDistance(&temppoint1, &temppoint2);
913 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
914 rotation2 *= 360 / 6.28;
917 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
918 rotation1 *= 360 / 6.28;
925 if (temppoint1.x > temppoint2.x) {
926 rotation1 = 360 - rotation1;
930 if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
931 freetime += multiplier;
941 multiplier = tempmult;
942 if (blooddrip && bloody) {
943 blooddripdelay -= blooddrip * multiplier / 2;
944 blooddrip -= multiplier;
951 if (blooddripdelay < 0 && bloodtoggle) {
955 bloodloc = position + (tippoint - position) * .7;
959 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
964 flamedelay -= multiplier;
965 if (onfire && flamedelay <= 0) {
967 flamedelay -= multiplier;
970 normalrot = Person::players[owner]->velocity;
974 if (Person::players[owner]->onterrain) {
978 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);
979 Sprite::setLastSpriteSpeed(4);
980 Sprite::setLastSpriteAlivetime(.3);
984 if (!onfire && owner == -1 && type != staff) {
985 flamedelay -= multiplier;
986 if (flamedelay <= 0) {
988 flamedelay -= multiplier;
990 if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
992 shinepoint = position + (tippoint - position) * (((float)abs(Random() % 100)) / 100);
993 Sprite::MakeSprite(weaponshinesprite, shinepoint, normalrot, 1, 1, 1, (.1 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3 * fast_sqrt(findDistance(&shinepoint, &viewer)), 1);
994 Sprite::setLastSpriteSpeed(4);
995 Sprite::setLastSpriteAlivetime(.3);
1001 void Weapons::DoStuff()
1005 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
1006 weapon->doStuff(i++);
1012 static XYZ terrainlight;
1013 static GLfloat M[16];
1015 if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
1016 distsq(&viewer, &position) < viewdistance * viewdistance)) {
1020 if (velocity.x && !physics) {
1026 if (Person::players[owner]->occluded < 25) {
1027 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) {
1032 (Person::players[owner]->animTarget == knifeslashstartanim ||
1033 Person::players[owner]->animTarget == swordsneakattackanim ||
1034 (Person::players[owner]->animCurrent == staffhitanim && Person::players[owner]->frameCurrent > 1) ||
1035 (Person::players[owner]->animCurrent == staffhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
1036 (Person::players[owner]->animCurrent == staffspinhitanim && Person::players[owner]->frameCurrent > 1) ||
1037 (Person::players[owner]->animCurrent == staffspinhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
1038 (Person::players[owner]->animCurrent == staffgroundsmashanim && Person::players[owner]->frameCurrent > 1) ||
1039 (Person::players[owner]->animTarget == swordslashanim && Person::players[owner]->frameTarget < 7) ||
1040 Person::players[owner]->animTarget == crouchstabanim ||
1041 Person::players[owner]->animTarget == swordslashreversalanim ||
1042 Person::players[owner]->animTarget == swordslashreversedanim ||
1043 Person::players[owner]->animTarget == knifefollowanim ||
1044 Person::players[owner]->animTarget == swordgroundstabanim ||
1045 Person::players[owner]->animTarget == knifethrowanim) &&
1046 Person::players[owner]->animTarget == lastdrawnanim &&
1047 !Person::players[owner]->skeleton.free) {
1052 if (Person::players[owner]->animTarget == swordgroundstabanim) {
1053 lastdrawnrotation1 = rotation1;
1054 lastdrawnrotation2 = rotation2;
1055 lastdrawnrotation3 = rotation3;
1056 lastdrawnbigrotation = bigrotation;
1057 lastdrawnbigtilt = bigtilt;
1058 lastdrawnbigtilt2 = bigtilt2;
1059 lastdrawnsmallrotation = smallrotation;
1060 lastdrawnsmallrotation2 = smallrotation2;
1064 terrainlight = terrain.getLighting(position.x, position.z);
1065 if (drawhowmany > 0) {
1066 glAlphaFunc(GL_GREATER, 0.01);
1068 for (int j = drawhowmany; j > 0; j--) {
1069 glMatrixMode(GL_MODELVIEW);
1071 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
1073 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));
1075 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));
1077 glRotatef(bigrotation * (((float)(j)) / drawhowmany) + lastdrawnbigrotation * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1078 glRotatef(bigtilt2 * (((float)(j)) / drawhowmany) + lastdrawnbigtilt2 * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
1079 glRotatef(bigtilt * (((float)(j)) / drawhowmany) + lastdrawnbigtilt * (1 - ((float)(j)) / drawhowmany), 0, 0, 1);
1080 glRotatef(-rotation1 * (((float)(j)) / drawhowmany) - lastdrawnrotation1 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 1, 0);
1081 glRotatef(-rotation2 * (((float)(j)) / drawhowmany) - lastdrawnrotation2 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 0, 1);
1082 glRotatef(-rotation3 * (((float)(j)) / drawhowmany) - lastdrawnrotation3 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1083 glRotatef(smallrotation * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
1084 glRotatef(smallrotation2 * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation2 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1087 if (Person::players[owner]->animTarget == staffhitanim || Person::players[owner]->animCurrent == staffhitanim || Person::players[owner]->animTarget == staffhitreversedanim || Person::players[owner]->animCurrent == staffhitreversedanim) {
1088 glTranslatef(0, 0, -.3);
1090 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) {
1091 glTranslatef(0, 0, -.1);
1095 glEnable(GL_LIGHTING);
1098 if (!bloody || !bloodtoggle) {
1099 throwingknifemodel.drawdifftex(knifetextureptr);
1103 throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1106 throwingknifemodel.drawdifftex(bloodknifetextureptr);
1111 if (!bloody || !bloodtoggle) {
1112 swordmodel.drawdifftex(swordtextureptr);
1116 swordmodel.drawdifftex(lightbloodswordtextureptr);
1119 swordmodel.drawdifftex(bloodswordtextureptr);
1124 staffmodel.drawdifftex(stafftextureptr);
1131 lastdrawnposition = position;
1132 lastdrawntippoint = tippoint;
1133 lastdrawnrotation1 = rotation1;
1134 lastdrawnrotation2 = rotation2;
1135 lastdrawnrotation3 = rotation3;
1136 lastdrawnbigrotation = bigrotation;
1137 lastdrawnbigtilt = bigtilt;
1138 lastdrawnbigtilt2 = bigtilt2;
1139 lastdrawnsmallrotation = smallrotation;
1140 lastdrawnsmallrotation2 = smallrotation2;
1142 lastdrawnanim = Person::players[owner]->animCurrent;
1146 glMatrixMode(GL_MODELVIEW);
1149 glTranslatef(position.x, position.y - .02, position.z);
1150 glRotatef(bigrotation, 0, 1, 0);
1151 glRotatef(bigtilt2, 1, 0, 0);
1152 glRotatef(bigtilt, 0, 0, 1);
1153 glRotatef(-rotation1 + 90, 0, 1, 0);
1154 glRotatef(-rotation2 + 90, 0, 0, 1);
1155 glRotatef(-rotation3, 0, 1, 0);
1156 glRotatef(smallrotation, 1, 0, 0);
1157 glRotatef(smallrotation2, 0, 1, 0);
1158 glTranslatef(0, 0, length);
1159 glGetFloatv(GL_MODELVIEW_MATRIX, M);
1168 void Weapon::drop(XYZ v, XYZ tv, bool sethitsomething)
1174 if (sethitsomething) {
1182 void Weapon::thrown(XYZ v, bool sethitsomething)
1184 drop(v, v, sethitsomething);
1191 glAlphaFunc(GL_GREATER, 0.9);
1192 glEnable(GL_TEXTURE_2D);
1194 glEnable(GL_CULL_FACE);
1195 glCullFace(GL_FRONT);
1198 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {