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/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 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)
81 void Weapon::setType(int t)
101 /* Load weapons models and textures */
104 LOG("Loading weapon data...");
106 knifetextureptr.load("Textures/Knife.png", 0);
107 bloodknifetextureptr.load("Textures/BloodKnife.png", 0);
108 lightbloodknifetextureptr.load("Textures/BloodKnifeLight.png", 0);
109 swordtextureptr.load("Textures/Sword.jpg", 1);
110 bloodswordtextureptr.load("Textures/SwordBlood.jpg", 1);
111 lightbloodswordtextureptr.load("Textures/SwordBloodLight.jpg", 1);
112 stafftextureptr.load("Textures/Staff.jpg", 1);
114 throwingknifemodel.load("Models/ThrowingKnife.solid");
115 throwingknifemodel.Scale(.001, .001, .001);
116 throwingknifemodel.Rotate(90, 0, 0);
117 throwingknifemodel.Rotate(0, 90, 0);
118 throwingknifemodel.flat = 0;
119 throwingknifemodel.CalculateNormals(1);
121 swordmodel.load("Models/Sword.solid");
122 swordmodel.Scale(.001, .001, .001);
123 swordmodel.Rotate(90, 0, 0);
124 swordmodel.Rotate(0, 90, 0);
125 swordmodel.Rotate(0, 0, 90);
127 swordmodel.CalculateNormals(1);
129 staffmodel.load("Models/Staff.solid");
130 staffmodel.Scale(.005, .005, .005);
131 staffmodel.Rotate(90, 0, 0);
132 staffmodel.Rotate(0, 90, 0);
133 staffmodel.Rotate(0, 0, 90);
135 staffmodel.CalculateNormals(1);
138 void Weapon::doStuff(int i)
140 static int whichpatchx, whichpatchz, whichhit;
141 static XYZ start, end, colpoint, normalrot, footvel, footpoint;
142 static XYZ terrainnormal;
145 static XYZ newpoint1, newpoint2;
146 static float friction = 3.5;
147 static float elasticity = .4;
148 static XYZ bounceness;
149 static float frictionness;
150 static float closestdistance;
151 static float distance;
153 static XYZ closestpoint;
154 static XYZ closestswordpoint;
155 static float tempmult;
157 if (multiplier <= 0) {
164 if (damage >= 2 && type == staff && owner != -1) { // the staff breaks
165 emit_sound_at(staffbreaksound, tippoint);
167 for (int j = 0; j < 40; j++) {
168 tempvel.x = float(abs(Random() % 100) - 50) / 20;
169 tempvel.y = float(abs(Random() % 100) - 50) / 20;
170 tempvel.z = float(abs(Random() % 100) - 50) / 20;
171 Sprite::MakeSprite(splintersprite, position + (tippoint - position) * ((float)j - 8) / 32, tempvel * .5, 115 / 255, 73 / 255, 12 / 255, .1, 1);
174 Person::players[owner]->weaponactive = -1;
175 Person::players[owner]->num_weapons--;
176 if (Person::players[owner]->num_weapons) {
177 Person::players[owner]->weaponids[0] = Person::players[owner]->weaponids[Person::players[owner]->num_weapons];
178 if (Person::players[owner]->weaponstuck == Person::players[owner]->num_weapons) {
179 Person::players[owner]->weaponstuck = 0;
191 oldposition = position;
192 oldtippoint = tippoint;
193 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && !physics) { // if the weapon is flying
194 position += velocity * multiplier;
195 tippoint += velocity * multiplier;
196 whichpatchx = position.x / (terrain.size / subdivision * terrain.scale);
197 whichpatchz = position.z / (terrain.size / subdivision * terrain.scale);
198 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
199 for (unsigned int j = 0; j < terrain.patchobjects[whichpatchx][whichpatchz].size(); j++) { // check for collision
200 unsigned int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
203 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
204 if (whichhit != -1) {
205 if (Object::objects[k]->type == treetrunktype) {
206 Object::objects[k]->model.MakeDecal(breakdecal, DoRotation(colpoint - Object::objects[k]->position, 0, -Object::objects[k]->yaw, 0), .1, 1, Random() % 360);
207 normalrot = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0);
210 position = colpoint - normalrot * .1;
211 } else if (type == sword) {
212 position = colpoint - normalrot * .2;
213 } else if (type == staff) {
214 position = colpoint - normalrot * .2;
216 XYZ temppoint1, temppoint2;
220 temppoint2 = normalrot;
221 distance = findDistance(&temppoint1, &temppoint2);
222 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
223 rotation2 *= 360 / 6.28;
226 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
227 rotation1 *= 360 / 6.28;
228 if (temppoint1.x > temppoint2.x) {
229 rotation1 = 360 - rotation1;
239 emit_sound_at(knifesheathesound, position, 128.);
243 Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
247 position -= velocity * multiplier;
248 tippoint -= velocity * multiplier;
249 tipvelocity = velocity;
255 if (velocity.x || velocity.y || velocity.z) {
256 for (unsigned j = 0; j < Person::players.size(); j++) {
258 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;
259 if (owner == -1 && distsqflat(&position, &Person::players[j]->coords) < 1.5 &&
260 distsq(&position, &Person::players[j]->coords) < 4 && Person::players[j]->weaponstuck == -1 &&
261 !Person::players[j]->skeleton.free && (int(j) != oldowner)) {
262 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) {
263 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)) ||
264 (Person::players[j]->creature == rabbittype && Random() % 2 == 0 && Person::players[j]->aitype == attacktypecutoff && Person::players[j]->weaponactive == -1)) {
265 emit_sound_at(knifedrawsound, Person::players[j]->coords, 128.);
267 Person::players[j]->animTarget = removeknifeanim;
268 Person::players[j]->frameTarget = 1;
269 Person::players[j]->target = 1;
270 Person::players[j]->takeWeapon(i);
272 Person::players[j]->aitype = attacktypecutoff;
277 Person::players[j]->num_weapons++;
278 Person::players[j]->weaponstuck = Person::players[j]->num_weapons - 1;
279 if (normaldotproduct(Person::players[j]->facing, velocity) > 0) {
280 Person::players[j]->weaponstuckwhere = 1;
282 Person::players[j]->weaponstuckwhere = 0;
285 Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
287 Person::players[j]->RagDoll(0);
288 Person::players[j]->jointVel(abdomen) += velocity * 2;
289 Person::players[j]->jointVel(neck) += velocity * 2;
290 Person::players[j]->jointVel(rightshoulder) += velocity * 2;
291 Person::players[j]->jointVel(leftshoulder) += velocity * 2;
292 if (bloodtoggle && !Tutorial::active) {
293 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
295 if (Tutorial::active) {
296 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
298 footvel = tippoint - position;
300 if (bloodtoggle && !Tutorial::active) {
301 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
304 if (!Tutorial::active) {
305 if (Person::players[j]->weaponstuckwhere == 0) {
306 Person::players[j]->DoBloodBig(2, 205);
308 if (Person::players[j]->weaponstuckwhere == 1) {
309 Person::players[j]->DoBloodBig(2, 200);
311 Person::players[j]->damage += 200 / Person::players[j]->armorhigh;
312 Person::players[j]->deathbleeding = 1;
313 Person::players[j]->bloodloss += (200 + abs((float)(Random() % 40)) - 20) / Person::players[j]->armorhigh;
319 emit_sound_at(fleshstabsound, position, 128.);
321 if (Animation::animations[Person::players[0]->animTarget].height == highheight) {
322 award_bonus(0, ninja);
324 award_bonus(0, Bullseyebonus);
333 if (position.y < terrain.getHeight(position.x, position.z)) {
334 if (terrain.getOpacity(position.x, position.z) < .2) {
336 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
337 position = colpoint * terrain.scale;
339 position.y = terrain.getHeight(position.x, position.z);
342 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
343 normalrot = terrain.getNormal(position.x, position.z) * -1;
345 glMatrixMode(GL_MODELVIEW);
349 glRotatef(bigrotation, 0, 1, 0);
350 glRotatef(bigtilt2, 1, 0, 0);
351 glRotatef(bigtilt, 0, 0, 1);
352 glRotatef(-rotation1 + 90, 0, 1, 0);
353 glRotatef(-rotation2 + 90, 0, 0, 1);
354 glRotatef(-rotation3, 0, 1, 0);
355 glRotatef(smallrotation, 1, 0, 0);
356 glRotatef(smallrotation2, 0, 1, 0);
357 glTranslatef(0, 0, 1);
358 glGetFloatv(GL_MODELVIEW_MATRIX, M);
363 position -= tippoint * .15;
364 XYZ temppoint1, temppoint2;
373 emit_sound_at(knifesheathesound, position, 128.);
376 terrainlight = terrain.getLighting(position.x, position.z);
377 if (environment == snowyenvironment) {
378 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
379 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
381 } else if (environment == grassyenvironment) {
382 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
383 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
385 } else if (environment == desertenvironment) {
386 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
387 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
395 position -= velocity * multiplier;
396 tippoint -= velocity * multiplier;
397 tipvelocity = velocity;
400 if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
401 velocity.y += gravity * multiplier;
403 XYZ temppoint1, temppoint2;
407 temppoint2 = velocity;
408 distance = findDistance(&temppoint1, &temppoint2);
409 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
410 rotation2 *= 360 / 6.28;
413 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
414 rotation1 *= 360 / 6.28;
421 if (temppoint1.x > temppoint2.x) {
422 rotation1 = 360 - rotation1;
432 tempmult = multiplier;
434 for (int l = 0; l < 10; l++) {
435 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
437 position += velocity * multiplier;
438 tippoint += tipvelocity * multiplier;
441 midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
442 vel = tippoint - midp;
444 newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
445 newpoint2 = midp + vel * length * (mass / (mass + tipmass));
447 if (freetime > .04) {
448 velocity = velocity + (newpoint1 - position) / multiplier;
449 tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
452 position = newpoint1;
453 tippoint = newpoint2;
456 whichpatchx = (position.x) / (terrain.size / subdivision * terrain.scale);
457 whichpatchz = (position.z) / (terrain.size / subdivision * terrain.scale);
458 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
459 for (unsigned int j = 0; j < terrain.patchobjects[whichpatchx][whichpatchz].size(); j++) {
460 unsigned int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
464 start = tippoint - (position - tippoint) / 5;
465 end = position + (position - tippoint) / 30;
466 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
467 if (whichhit != -1) {
469 diff = (colpoint - position);
473 tippoint += (colpoint - position) + diff * .05;
474 position = colpoint + diff * .05;
475 oldtippoint = tippoint;
476 oldposition = tippoint;
479 start = position - (tippoint - position) / 5;
480 end = tippoint + (tippoint - position) / 30;
481 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
482 if (whichhit != -1) {
484 diff = (colpoint - tippoint);
488 position += (colpoint - tippoint) + diff * .05;
489 tippoint = colpoint + diff * .05;
490 oldposition = position;
491 oldtippoint = tippoint;
498 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
499 if (whichhit != -1) {
502 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
503 ReflectVector(&velocity, &terrainnormal);
504 position += terrainnormal * .002;
506 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
507 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
510 frictionness = abs(normaldotproduct(velocity, terrainnormal));
511 velocity -= bounceness;
512 if (1 - friction * frictionness > 0) {
513 velocity *= 1 - friction * frictionness;
517 velocity += bounceness * elasticity;
519 if (findLengthfast(&bounceness) > 1) {
522 whichsound = footstepsound3 + abs(Random() % 2);
524 whichsound = clank1sound + abs(Random() % 4);
526 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
531 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
532 if (whichhit != -1) {
535 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
536 ReflectVector(&tipvelocity, &terrainnormal);
537 tippoint += terrainnormal * .002;
539 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
540 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
543 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
544 tipvelocity -= bounceness;
545 if (1 - friction * frictionness > 0) {
546 tipvelocity *= 1 - friction * frictionness;
550 tipvelocity += bounceness * elasticity;
552 if (findLengthfast(&bounceness) > 1) {
555 whichsound = footstepsound3 + abs(Random() % 2);
557 whichsound = clank1sound + abs(Random() % 4);
559 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
563 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) {
564 for (int m = 0; m < 2; m++) {
565 mid = (position * (21 + (float)m * 10) + tippoint * (19 - (float)m * 10)) / 40;
567 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
571 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
572 if (whichhit != -1) {
575 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
576 ReflectVector(&velocity, &terrainnormal);
578 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
579 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
582 frictionness = abs(normaldotproduct(velocity, terrainnormal));
583 velocity -= bounceness;
584 if (1 - friction * frictionness > 0) {
585 velocity *= 1 - friction * frictionness;
589 velocity += bounceness * elasticity;
591 if (findLengthfast(&bounceness) > 1) {
594 whichsound = footstepsound3 + abs(Random() % 2);
596 whichsound = clank1sound + abs(Random() % 4);
598 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
600 position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
603 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
605 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
609 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
610 if (whichhit != -1) {
613 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
614 ReflectVector(&tipvelocity, &terrainnormal);
616 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
617 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
620 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
621 tipvelocity -= bounceness;
622 if (1 - friction * frictionness > 0) {
623 tipvelocity *= 1 - friction * frictionness;
627 tipvelocity += bounceness * elasticity;
629 if (findLengthfast(&bounceness) > 1) {
632 whichsound = footstepsound3 + abs(Random() % 2);
634 whichsound = clank1sound + abs(Random() % 4);
636 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
638 tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
644 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
645 if (whichhit != -1) {
647 closestdistance = -1;
648 closestswordpoint = colpoint;
649 point[0] = DoRotation(Object::objects[k]->model.getTriangleVertex(whichhit, 0), 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
650 point[1] = DoRotation(Object::objects[k]->model.getTriangleVertex(whichhit, 1), 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
651 point[2] = DoRotation(Object::objects[k]->model.getTriangleVertex(whichhit, 2), 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
652 if (DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance, &colpoint)) {
653 if (distance < closestdistance || closestdistance == -1) {
654 closestpoint = colpoint;
655 closestdistance = distance;
658 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint)) {
659 if (distance < closestdistance || closestdistance == -1) {
660 closestpoint = colpoint;
661 closestdistance = distance;
664 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint)) {
665 if (distance < closestdistance || closestdistance == -1) {
666 closestpoint = colpoint;
667 closestdistance = distance;
670 if (closestdistance != -1 && isnormal(closestdistance)) {
671 if (DistancePointLine(&closestpoint, &position, &tippoint, &distance, &colpoint)) {
672 closestswordpoint = colpoint;
673 velocity += (closestpoint - closestswordpoint);
674 tipvelocity += (closestpoint - closestswordpoint);
675 position += (closestpoint - closestswordpoint);
676 tippoint += (closestpoint - closestswordpoint);
684 whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
685 if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
687 if (whichhit != -1) {
688 position = colpoint * terrain.scale;
690 position.y = terrain.getHeight(position.x, position.z);
693 terrainnormal = terrain.getNormal(position.x, position.z);
694 ReflectVector(&velocity, &terrainnormal);
695 position += terrainnormal * .002;
696 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
697 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
700 frictionness = abs(normaldotproduct(velocity, terrainnormal));
701 velocity -= bounceness;
702 if (1 - friction * frictionness > 0) {
703 velocity *= 1 - friction * frictionness;
707 if (terrain.getOpacity(position.x, position.z) < .2) {
708 velocity += bounceness * elasticity * .3;
710 velocity += bounceness * elasticity;
713 if (findLengthfast(&bounceness) > 1) {
715 if (terrain.getOpacity(position.x, position.z) > .2) {
717 whichsound = footstepsound3 + abs(Random() % 2);
719 whichsound = clank1sound + abs(Random() % 4);
722 whichsound = footstepsound + abs(Random() % 2);
724 emit_sound_at(whichsound, position,
725 findLengthfast(&bounceness) * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
727 if (terrain.getOpacity(position.x, position.z) < .2) {
729 terrainlight = terrain.getLighting(position.x, position.z);
730 if (environment == snowyenvironment) {
731 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
732 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
734 } else if (environment == grassyenvironment) {
735 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
736 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
738 } else if (environment == desertenvironment) {
739 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4) {
740 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
746 whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
747 if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
748 if (whichhit != -1) {
749 tippoint = colpoint * terrain.scale;
751 tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
754 terrainnormal = terrain.getNormal(tippoint.x, tippoint.z);
755 ReflectVector(&tipvelocity, &terrainnormal);
756 tippoint += terrainnormal * .002;
757 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
758 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
761 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
762 tipvelocity -= bounceness;
763 if (1 - friction * frictionness > 0) {
764 tipvelocity *= 1 - friction * frictionness;
768 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
769 tipvelocity += bounceness * elasticity * .3;
771 tipvelocity += bounceness * elasticity;
774 if (findLengthfast(&bounceness) > 1) {
776 if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
778 whichsound = footstepsound3 + abs(Random() % 2);
780 whichsound = clank1sound + abs(Random() % 4);
783 whichsound = footstepsound + abs(Random() % 2);
785 emit_sound_at(whichsound, tippoint,
786 findLengthfast(&bounceness) * (terrain.getOpacity(tippoint.x, tippoint.z) > .2 ? 128. : 32.));
788 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
790 terrainlight = terrain.getLighting(tippoint.x, tippoint.z);
791 if (environment == snowyenvironment) {
792 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4) {
793 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
795 } else if (environment == grassyenvironment) {
796 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4) {
797 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
799 } else if (environment == desertenvironment) {
800 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4) {
801 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
809 mid = position + tippoint;
811 mid += (position - mid) / 20;
813 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
815 mid.y = terrain.getHeight(mid.x, mid.z);
817 terrainnormal = terrain.getNormal(mid.x, mid.z);
818 ReflectVector(&velocity, &terrainnormal);
819 //mid+=terrainnormal*.002;
820 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
821 if (findLengthfast(&velocity) < findLengthfast(&bounceness)) {
824 frictionness = abs(normaldotproduct(velocity, terrainnormal));
825 velocity -= bounceness;
826 if (1 - friction * frictionness > 0) {
827 velocity *= 1 - friction * frictionness;
831 if (terrain.getOpacity(mid.x, mid.z) < .2) {
832 velocity += bounceness * elasticity * .3;
834 velocity += bounceness * elasticity;
837 if (findLengthfast(&bounceness) > 1) {
839 if (terrain.getOpacity(mid.x, mid.z) > .2) {
841 whichsound = footstepsound3 + abs(Random() % 2);
844 whichsound = clank1sound + abs(Random() % 4);
847 whichsound = footstepsound + abs(Random() % 2);
849 emit_sound_at(whichsound, mid,
850 findLengthfast(&bounceness) * (terrain.getOpacity(position.x, position.z) > .2
854 position += (mid - oldmid) * 20;
857 mid = position + tippoint;
859 mid += (tippoint - mid) / 20;
861 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
863 mid.y = terrain.getHeight(mid.x, mid.z);
865 terrainnormal = terrain.getNormal(mid.x, mid.z);
866 ReflectVector(&tipvelocity, &terrainnormal);
867 //mid+=terrainnormal*.002;
868 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
869 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness)) {
872 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
873 tipvelocity -= bounceness;
874 if (1 - friction * frictionness > 0) {
875 tipvelocity *= 1 - friction * frictionness;
879 if (terrain.getOpacity(mid.x, mid.z) < .2) {
880 tipvelocity += bounceness * elasticity * .3;
882 tipvelocity += bounceness * elasticity;
885 if (findLengthfast(&bounceness) > 1) {
887 if (terrain.getOpacity(mid.x, mid.z) > .2) {
889 whichsound = footstepsound3 + abs(Random() % 2);
892 whichsound = clank1sound + abs(Random() % 4);
895 whichsound = footstepsound + abs(Random() % 2);
897 emit_sound_at(whichsound, mid,
898 findLengthfast(&bounceness) * (terrain.getOpacity(position.x, position.z) > .2
902 tippoint += (mid - oldmid) * 20;
905 velocity.y += gravity * multiplier;
906 tipvelocity.y += gravity * multiplier;
909 XYZ temppoint1, temppoint2;
912 temppoint1 = position;
913 temppoint2 = tippoint;
914 distance = findDistance(&temppoint1, &temppoint2);
915 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
916 rotation2 *= 360 / 6.28;
919 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
920 rotation1 *= 360 / 6.28;
927 if (temppoint1.x > temppoint2.x) {
928 rotation1 = 360 - rotation1;
932 if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
933 freetime += multiplier;
943 multiplier = tempmult;
944 if (blooddrip && bloody) {
945 blooddripdelay -= blooddrip * multiplier / 2;
946 blooddrip -= multiplier;
953 if (blooddripdelay < 0 && bloodtoggle) {
957 bloodloc = position + (tippoint - position) * .7;
961 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
966 flamedelay -= multiplier;
967 if (onfire && flamedelay <= 0) {
969 flamedelay -= multiplier;
972 normalrot = Person::players[owner]->velocity;
976 if (Person::players[owner]->onterrain) {
980 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);
981 Sprite::setLastSpriteSpeed(4);
982 Sprite::setLastSpriteAlivetime(.3);
986 if (!onfire && owner == -1 && type != staff) {
987 flamedelay -= multiplier;
988 if (flamedelay <= 0) {
990 flamedelay -= multiplier;
992 if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
994 shinepoint = position + (tippoint - position) * (((float)abs(Random() % 100)) / 100);
995 Sprite::MakeSprite(weaponshinesprite, shinepoint, normalrot, 1, 1, 1, (.1 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3 * fast_sqrt(findDistance(&shinepoint, &viewer)), 1);
996 Sprite::setLastSpriteSpeed(4);
997 Sprite::setLastSpriteAlivetime(.3);
1003 void Weapons::DoStuff()
1007 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
1008 weapon->doStuff(i++);
1014 static XYZ terrainlight;
1015 static GLfloat M[16];
1017 if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
1018 distsq(&viewer, &position) < viewdistance * viewdistance)) {
1022 if (velocity.x && !physics) {
1028 if (Person::players[owner]->occluded < 25) {
1029 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) {
1034 (Person::players[owner]->animTarget == knifeslashstartanim ||
1035 Person::players[owner]->animTarget == swordsneakattackanim ||
1036 (Person::players[owner]->animCurrent == staffhitanim && Person::players[owner]->frameCurrent > 1) ||
1037 (Person::players[owner]->animCurrent == staffhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
1038 (Person::players[owner]->animCurrent == staffspinhitanim && Person::players[owner]->frameCurrent > 1) ||
1039 (Person::players[owner]->animCurrent == staffspinhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
1040 (Person::players[owner]->animCurrent == staffgroundsmashanim && Person::players[owner]->frameCurrent > 1) ||
1041 (Person::players[owner]->animTarget == swordslashanim && Person::players[owner]->frameTarget < 7) ||
1042 Person::players[owner]->animTarget == crouchstabanim ||
1043 Person::players[owner]->animTarget == swordslashreversalanim ||
1044 Person::players[owner]->animTarget == swordslashreversedanim ||
1045 Person::players[owner]->animTarget == knifefollowanim ||
1046 Person::players[owner]->animTarget == swordgroundstabanim ||
1047 Person::players[owner]->animTarget == knifethrowanim) &&
1048 Person::players[owner]->animTarget == lastdrawnanim &&
1049 !Person::players[owner]->skeleton.free) {
1054 if (Person::players[owner]->animTarget == swordgroundstabanim) {
1055 lastdrawnrotation1 = rotation1;
1056 lastdrawnrotation2 = rotation2;
1057 lastdrawnrotation3 = rotation3;
1058 lastdrawnbigrotation = bigrotation;
1059 lastdrawnbigtilt = bigtilt;
1060 lastdrawnbigtilt2 = bigtilt2;
1061 lastdrawnsmallrotation = smallrotation;
1062 lastdrawnsmallrotation2 = smallrotation2;
1066 terrainlight = terrain.getLighting(position.x, position.z);
1067 if (drawhowmany > 0) {
1068 glAlphaFunc(GL_GREATER, 0.01);
1070 for (int j = drawhowmany; j > 0; j--) {
1071 glMatrixMode(GL_MODELVIEW);
1073 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
1075 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));
1077 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));
1079 glRotatef(bigrotation * (((float)(j)) / drawhowmany) + lastdrawnbigrotation * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1080 glRotatef(bigtilt2 * (((float)(j)) / drawhowmany) + lastdrawnbigtilt2 * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
1081 glRotatef(bigtilt * (((float)(j)) / drawhowmany) + lastdrawnbigtilt * (1 - ((float)(j)) / drawhowmany), 0, 0, 1);
1082 glRotatef(-rotation1 * (((float)(j)) / drawhowmany) - lastdrawnrotation1 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 1, 0);
1083 glRotatef(-rotation2 * (((float)(j)) / drawhowmany) - lastdrawnrotation2 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 0, 1);
1084 glRotatef(-rotation3 * (((float)(j)) / drawhowmany) - lastdrawnrotation3 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1085 glRotatef(smallrotation * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
1086 glRotatef(smallrotation2 * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation2 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1089 if (Person::players[owner]->animTarget == staffhitanim || Person::players[owner]->animCurrent == staffhitanim || Person::players[owner]->animTarget == staffhitreversedanim || Person::players[owner]->animCurrent == staffhitreversedanim) {
1090 glTranslatef(0, 0, -.3);
1092 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) {
1093 glTranslatef(0, 0, -.1);
1097 glEnable(GL_LIGHTING);
1100 if (!bloody || !bloodtoggle) {
1101 throwingknifemodel.drawdifftex(knifetextureptr);
1105 throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1108 throwingknifemodel.drawdifftex(bloodknifetextureptr);
1113 if (!bloody || !bloodtoggle) {
1114 swordmodel.drawdifftex(swordtextureptr);
1118 swordmodel.drawdifftex(lightbloodswordtextureptr);
1121 swordmodel.drawdifftex(bloodswordtextureptr);
1126 staffmodel.drawdifftex(stafftextureptr);
1133 lastdrawnposition = position;
1134 lastdrawntippoint = tippoint;
1135 lastdrawnrotation1 = rotation1;
1136 lastdrawnrotation2 = rotation2;
1137 lastdrawnrotation3 = rotation3;
1138 lastdrawnbigrotation = bigrotation;
1139 lastdrawnbigtilt = bigtilt;
1140 lastdrawnbigtilt2 = bigtilt2;
1141 lastdrawnsmallrotation = smallrotation;
1142 lastdrawnsmallrotation2 = smallrotation2;
1144 lastdrawnanim = Person::players[owner]->animCurrent;
1148 glMatrixMode(GL_MODELVIEW);
1151 glTranslatef(position.x, position.y - .02, position.z);
1152 glRotatef(bigrotation, 0, 1, 0);
1153 glRotatef(bigtilt2, 1, 0, 0);
1154 glRotatef(bigtilt, 0, 0, 1);
1155 glRotatef(-rotation1 + 90, 0, 1, 0);
1156 glRotatef(-rotation2 + 90, 0, 0, 1);
1157 glRotatef(-rotation3, 0, 1, 0);
1158 glRotatef(smallrotation, 1, 0, 0);
1159 glRotatef(smallrotation2, 0, 1, 0);
1160 glTranslatef(0, 0, length);
1161 glGetFloatv(GL_MODELVIEW_MATRIX, M);
1170 void Weapon::drop(XYZ v, XYZ tv, bool sethitsomething)
1176 if (sethitsomething) {
1184 void Weapon::thrown(XYZ v, bool sethitsomething)
1186 drop(v, v, sethitsomething);
1193 glAlphaFunc(GL_GREATER, 0.9);
1194 glEnable(GL_TEXTURE_2D);
1196 glEnable(GL_CULL_FACE);
1197 glCullFace(GL_FRONT);
1200 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {