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"
31 extern float multiplier;
32 extern Terrain terrain;
34 extern int environment;
36 extern FRUSTUM frustum;
38 extern float realmultiplier;
40 extern float slomodelay;
41 extern bool cellophane;
42 extern float texdetail;
43 extern GLubyte bloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
52 extern int tutoriallevel;
53 extern int numthrowkill;
55 Model Weapon::throwingknifemodel;
56 Texture Weapon::knifetextureptr;
57 Texture Weapon::lightbloodknifetextureptr;
58 Texture Weapon::bloodknifetextureptr;
60 Model Weapon::swordmodel;
61 Texture Weapon::swordtextureptr;
62 Texture Weapon::lightbloodswordtextureptr;
63 Texture Weapon::bloodswordtextureptr;
65 Model Weapon::staffmodel;
66 Texture Weapon::stafftextureptr;
68 Weapon::Weapon(int t, int o) : owner(o)
81 void Weapon::setType(int t)
101 void Weapon::DoStuff(int i)
103 //~ cout << position.x << "," << position.y << "," << position.z << "|" << tippoint.x << "," << tippoint.y << "," << tippoint.z << endl;
104 static int whichpatchx, whichpatchz, whichhit;
105 static XYZ start, end, colpoint, normalrot, footvel, footpoint;
106 static XYZ terrainnormal;
109 static XYZ newpoint1, newpoint2;
110 static float friction = 3.5;
111 static float elasticity = .4;
112 static XYZ bounceness;
113 static float frictionness;
114 static float closestdistance;
115 static float distance;
117 static XYZ closestpoint;
118 static XYZ closestswordpoint;
119 static float tempmult;
124 if (damage >= 2 && type == staff && owner != -1) { // the staff breaks
125 emit_sound_at(staffbreaksound, tippoint);
127 for (int j = 0; j < 40; j++) {
128 tempvel.x = float(abs(Random() % 100) - 50) / 20;
129 tempvel.y = float(abs(Random() % 100) - 50) / 20;
130 tempvel.z = float(abs(Random() % 100) - 50) / 20;
131 Sprite::MakeSprite(splintersprite, position + (tippoint - position) * ((float)j - 8) / 32, tempvel * .5, 115 / 255, 73 / 255, 12 / 255, .1, 1);
134 Person::players[owner]->weaponactive = -1;
135 Person::players[owner]->num_weapons--;
136 if (Person::players[owner]->num_weapons) {
137 Person::players[owner]->weaponids[0] = Person::players[owner]->weaponids[Person::players[owner]->num_weapons];
138 if (Person::players[owner]->weaponstuck == Person::players[owner]->num_weapons)
139 Person::players[owner]->weaponstuck = 0;
150 oldposition = position;
151 oldtippoint = tippoint;
152 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && !physics) { // if the weapon is flying
153 position += velocity * multiplier;
154 tippoint += velocity * multiplier;
155 whichpatchx = position.x / (terrain.size / subdivision * terrain.scale);
156 whichpatchz = position.z / (terrain.size / subdivision * terrain.scale);
157 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
158 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) { // if there are objects where the weapon is
159 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) { // check for collision
160 int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
163 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
164 if (whichhit != -1) {
165 if (objects.type[k] == treetrunktype) {
166 objects.model[k].MakeDecal(breakdecal, DoRotation(colpoint - objects.position[k], 0, -objects.yaw[k], 0), .1, 1, Random() % 360);
167 normalrot = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0);
170 position = colpoint - normalrot * .1;
171 else if (type == sword)
172 position = colpoint - normalrot * .2;
173 else if (type == staff)
174 position = colpoint - normalrot * .2;
175 XYZ temppoint1, temppoint2;
179 temppoint2 = normalrot;
180 distance = findDistance(&temppoint1, &temppoint2);
181 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
182 rotation2 *= 360 / 6.28;
185 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
186 rotation1 *= 360 / 6.28;
187 if (temppoint1.x > temppoint2.x)
188 rotation1 = 360 - rotation1;
197 emit_sound_at(knifesheathesound, position, 128.);
201 Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
205 position -= velocity * multiplier;
206 tippoint -= velocity * multiplier;
207 tipvelocity = velocity;
214 if (velocity.x || velocity.y || velocity.z) {
215 for (unsigned j = 0; j < Person::players.size(); j++) {
217 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;
218 if (owner == -1 && distsqflat(&position, &Person::players[j]->coords) < 1.5 &&
219 distsq(&position, &Person::players[j]->coords) < 4 && Person::players[j]->weaponstuck == -1 &&
220 !Person::players[j]->skeleton.free && (int(j) != oldowner)) {
221 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) {
222 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)) ||
223 (Person::players[j]->creature == rabbittype && Random() % 2 == 0 && Person::players[j]->aitype == attacktypecutoff && Person::players[j]->weaponactive == -1)) {
224 emit_sound_at(knifedrawsound, Person::players[j]->coords, 128.);
226 Person::players[j]->animTarget = removeknifeanim;
227 Person::players[j]->frameTarget = 1;
228 Person::players[j]->target = 1;
229 Person::players[j]->takeWeapon(i);
231 Person::players[j]->aitype = attacktypecutoff;
235 Person::players[j]->num_weapons++;
236 Person::players[j]->weaponstuck = Person::players[j]->num_weapons - 1;
237 if (normaldotproduct(Person::players[j]->facing, velocity) > 0)
238 Person::players[j]->weaponstuckwhere = 1;
240 Person::players[j]->weaponstuckwhere = 0;
242 Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
244 Person::players[j]->RagDoll(0);
245 Person::players[j]->jointVel(abdomen) += velocity * 2;
246 Person::players[j]->jointVel(neck) += velocity * 2;
247 Person::players[j]->jointVel(rightshoulder) += velocity * 2;
248 Person::players[j]->jointVel(leftshoulder) += velocity * 2;
249 if (bloodtoggle && tutoriallevel != 1)
250 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
251 if (tutoriallevel == 1)
252 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
253 footvel = tippoint - position;
255 if (bloodtoggle && tutoriallevel != 1)
256 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
258 if (tutoriallevel != 1) {
259 if (Person::players[j]->weaponstuckwhere == 0)
260 Person::players[j]->DoBloodBig(2, 205);
261 if (Person::players[j]->weaponstuckwhere == 1)
262 Person::players[j]->DoBloodBig(2, 200);
263 Person::players[j]->damage += 200 / Person::players[j]->armorhigh;
264 Person::players[j]->deathbleeding = 1;
265 Person::players[j]->bloodloss += (200 + abs((float)(Random() % 40)) - 20) / Person::players[j]->armorhigh;
271 emit_sound_at(fleshstabsound, position, 128.);
273 if (Animation::animations[Person::players[0]->animTarget].height == highheight)
274 award_bonus(0, ninja);
276 award_bonus(0, Bullseyebonus);
284 if (position.y < terrain.getHeight(position.x, position.z)) {
285 if (terrain.getOpacity(position.x, position.z) < .2) {
287 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
288 position = colpoint * terrain.scale;
290 position.y = terrain.getHeight(position.x, position.z);
293 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
294 normalrot = terrain.getNormal(position.x, position.z) * -1;
296 glMatrixMode(GL_MODELVIEW);
300 glRotatef(bigrotation, 0, 1, 0);
301 glRotatef(bigtilt2, 1, 0, 0);
302 glRotatef(bigtilt, 0, 0, 1);
303 glRotatef(-rotation1 + 90, 0, 1, 0);
304 glRotatef(-rotation2 + 90, 0, 0, 1);
305 glRotatef(-rotation3, 0, 1, 0);
306 glRotatef(smallrotation, 1, 0, 0);
307 glRotatef(smallrotation2, 0, 1, 0);
308 glTranslatef(0, 0, 1);
309 glGetFloatv(GL_MODELVIEW_MATRIX, M);
314 position -= tippoint * .15;
315 XYZ temppoint1, temppoint2;
324 emit_sound_at(knifesheathesound, position, 128.);
327 terrainlight = terrain.getLighting(position.x, position.z);
328 if (environment == snowyenvironment) {
329 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
330 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
331 } else if (environment == grassyenvironment) {
332 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
333 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
334 } else if (environment == desertenvironment) {
335 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
336 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
343 position -= velocity * multiplier;
344 tippoint -= velocity * multiplier;
345 tipvelocity = velocity;
348 if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
349 velocity.y += gravity * multiplier;
351 XYZ temppoint1, temppoint2;
355 temppoint2 = velocity;
356 distance = findDistance(&temppoint1, &temppoint2);
357 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
358 rotation2 *= 360 / 6.28;
361 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
362 rotation1 *= 360 / 6.28;
369 if (temppoint1.x > temppoint2.x)
370 rotation1 = 360 - rotation1;
380 tempmult = multiplier;
382 for (int l = 0; l < 10; l++) {
383 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
385 position += velocity * multiplier;
386 tippoint += tipvelocity * multiplier;
389 midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
390 vel = tippoint - midp;
392 newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
393 newpoint2 = midp + vel * length * (mass / (mass + tipmass));
395 if (freetime > .04) {
396 velocity = velocity + (newpoint1 - position) / multiplier;
397 tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
400 position = newpoint1;
401 tippoint = newpoint2;
405 whichpatchx = (position.x) / (terrain.size / subdivision * terrain.scale);
406 whichpatchz = (position.z) / (terrain.size / subdivision * terrain.scale);
407 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision)
408 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) {
409 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
410 int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
414 start = tippoint - (position - tippoint) / 5;
415 end = position + (position - tippoint) / 30;
416 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
417 if (whichhit != -1) {
419 diff = (colpoint - position);
423 tippoint += (colpoint - position) + diff * .05;
424 position = colpoint + diff * .05;
425 oldtippoint = tippoint;
426 oldposition = tippoint;
429 start = position - (tippoint - position) / 5;
430 end = tippoint + (tippoint - position) / 30;
431 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
432 if (whichhit != -1) {
434 diff = (colpoint - tippoint);
438 position += (colpoint - tippoint) + diff * .05;
439 tippoint = colpoint + diff * .05;
440 oldposition = position;
441 oldtippoint = tippoint;
448 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
449 if (whichhit != -1) {
452 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
453 ReflectVector(&velocity, &terrainnormal);
454 position += terrainnormal * .002;
456 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
457 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
459 frictionness = abs(normaldotproduct(velocity, terrainnormal));
460 velocity -= bounceness;
461 if (1 - friction * frictionness > 0)
462 velocity *= 1 - friction * frictionness;
465 velocity += bounceness * elasticity;
467 if (findLengthfast(&bounceness) > 1) {
470 whichsound = footstepsound3 + abs(Random() % 2);
472 whichsound = clank1sound + abs(Random() % 4);
473 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
478 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
479 if (whichhit != -1) {
482 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
483 ReflectVector(&tipvelocity, &terrainnormal);
484 tippoint += terrainnormal * .002;
486 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
487 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
489 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
490 tipvelocity -= bounceness;
491 if (1 - friction * frictionness > 0)
492 tipvelocity *= 1 - friction * frictionness;
495 tipvelocity += bounceness * elasticity;
497 if (findLengthfast(&bounceness) > 1) {
500 whichsound = footstepsound3 + abs(Random() % 2);
502 whichsound = clank1sound + abs(Random() % 4);
503 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
507 if ((objects.type[k] != boxtype && objects.type[k] != platformtype && objects.type[k] != walltype && objects.type[k] != weirdtype) || objects.pitch[k] != 0)
508 for (int m = 0; m < 2; m++) {
509 mid = (position * (21 + (float)m * 10) + tippoint * (19 - (float)m * 10)) / 40;
511 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
515 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
516 if (whichhit != -1) {
519 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
520 ReflectVector(&velocity, &terrainnormal);
522 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
523 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
525 frictionness = abs(normaldotproduct(velocity, terrainnormal));
526 velocity -= bounceness;
527 if (1 - friction * frictionness > 0)
528 velocity *= 1 - friction * frictionness;
531 velocity += bounceness * elasticity;
533 if (findLengthfast(&bounceness) > 1) {
536 whichsound = footstepsound3 + abs(Random() % 2);
538 whichsound = clank1sound + abs(Random() % 4);
539 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
541 position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
544 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
546 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
550 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
551 if (whichhit != -1) {
554 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
555 ReflectVector(&tipvelocity, &terrainnormal);
557 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
558 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
560 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
561 tipvelocity -= bounceness;
562 if (1 - friction * frictionness > 0)
563 tipvelocity *= 1 - friction * frictionness;
566 tipvelocity += bounceness * elasticity;
568 if (findLengthfast(&bounceness) > 1) {
571 whichsound = footstepsound3 + abs(Random() % 2);
573 whichsound = clank1sound + abs(Random() % 4);
574 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
576 tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
582 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
583 if (whichhit != -1) {
585 closestdistance = -1;
586 closestswordpoint = colpoint; //(position+tippoint)/2;
587 point[0] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[0]], 0, objects.yaw[k], 0) + objects.position[k];
588 point[1] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[1]], 0, objects.yaw[k], 0) + objects.position[k];
589 point[2] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[2]], 0, objects.yaw[k], 0) + objects.position[k];
590 if (DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance, &colpoint )) {
591 if (distance < closestdistance || closestdistance == -1) {
592 closestpoint = colpoint;
593 closestdistance = distance;
596 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint )) {
597 if (distance < closestdistance || closestdistance == -1) {
598 closestpoint = colpoint;
599 closestdistance = distance;
602 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint )) {
603 if (distance < closestdistance || closestdistance == -1) {
604 closestpoint = colpoint;
605 closestdistance = distance;
608 if (closestdistance != -1 && isnormal(closestdistance)) {
609 if (DistancePointLine(&closestpoint, &position, &tippoint, &distance, &colpoint )) {
610 closestswordpoint = colpoint;
611 velocity += (closestpoint - closestswordpoint);
612 tipvelocity += (closestpoint - closestswordpoint);
613 position += (closestpoint - closestswordpoint);
614 tippoint += (closestpoint - closestswordpoint);
622 whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
623 if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
626 position = colpoint * terrain.scale;
628 position.y = terrain.getHeight(position.x, position.z);
630 terrainnormal = terrain.getNormal(position.x, position.z);
631 ReflectVector(&velocity, &terrainnormal);
632 position += terrainnormal * .002;
633 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
634 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
636 frictionness = abs(normaldotproduct(velocity, terrainnormal));
637 velocity -= bounceness;
638 if (1 - friction * frictionness > 0)
639 velocity *= 1 - friction * frictionness;
642 if (terrain.getOpacity(position.x, position.z) < .2)
643 velocity += bounceness * elasticity * .3;
645 velocity += bounceness * elasticity;
647 if (findLengthfast(&bounceness) > 1) {
649 if (terrain.getOpacity(position.x, position.z) > .2) {
651 whichsound = footstepsound3 + abs(Random() % 2);
653 whichsound = clank1sound + abs(Random() % 4);
655 whichsound = footstepsound + abs(Random() % 2);
657 emit_sound_at(whichsound, position,
658 findLengthfast(&bounceness)
659 * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
661 if (terrain.getOpacity(position.x, position.z) < .2) {
663 terrainlight = terrain.getLighting(position.x, position.z);
664 if (environment == snowyenvironment) {
665 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
666 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
667 } else if (environment == grassyenvironment) {
668 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
669 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
670 } else if (environment == desertenvironment) {
671 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
672 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
677 whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
678 if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
680 tippoint = colpoint * terrain.scale;
682 tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
684 terrainnormal = terrain.getNormal(tippoint.x, tippoint.z);
685 ReflectVector(&tipvelocity, &terrainnormal);
686 tippoint += terrainnormal * .002;
687 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
688 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
690 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
691 tipvelocity -= bounceness;
692 if (1 - friction * frictionness > 0)
693 tipvelocity *= 1 - friction * frictionness;
696 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2)
697 tipvelocity += bounceness * elasticity * .3;
699 tipvelocity += bounceness * elasticity;
701 if (findLengthfast(&bounceness) > 1) {
703 if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
705 whichsound = footstepsound3 + abs(Random() % 2);
707 whichsound = clank1sound + abs(Random() % 4);
709 whichsound = footstepsound + abs(Random() % 2);
711 emit_sound_at(whichsound, tippoint,
712 findLengthfast(&bounceness)
713 * (terrain.getOpacity(tippoint.x, tippoint.z) > .2 ? 128. : 32.));
715 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
717 terrainlight = terrain.getLighting(tippoint.x, tippoint.z);
718 if (environment == snowyenvironment) {
719 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
720 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
721 } else if (environment == grassyenvironment) {
722 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
723 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
724 } else if (environment == desertenvironment) {
725 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
726 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
733 mid = position + tippoint;
735 mid += (position - mid) / 20;
737 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
739 mid.y = terrain.getHeight(mid.x, mid.z);
741 terrainnormal = terrain.getNormal(mid.x, mid.z);
742 ReflectVector(&velocity, &terrainnormal);
743 //mid+=terrainnormal*.002;
744 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
745 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
747 frictionness = abs(normaldotproduct(velocity, terrainnormal));
748 velocity -= bounceness;
749 if (1 - friction * frictionness > 0)
750 velocity *= 1 - friction * frictionness;
753 if (terrain.getOpacity(mid.x, mid.z) < .2)
754 velocity += bounceness * elasticity * .3;
756 velocity += bounceness * elasticity;
758 if (findLengthfast(&bounceness) > 1) {
760 if (terrain.getOpacity(mid.x, mid.z) > .2) {
762 whichsound = footstepsound3 + abs(Random() % 2);
764 whichsound = clank1sound + abs(Random() % 4);
766 whichsound = footstepsound + abs(Random() % 2);
768 emit_sound_at(whichsound, mid,
769 findLengthfast(&bounceness)
770 * (terrain.getOpacity(position.x, position.z) > .2
774 position += (mid - oldmid) * 20;
777 mid = position + tippoint;
779 mid += (tippoint - mid) / 20;
781 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
783 mid.y = terrain.getHeight(mid.x, mid.z);
785 terrainnormal = terrain.getNormal(mid.x, mid.z);
786 ReflectVector(&tipvelocity, &terrainnormal);
787 //mid+=terrainnormal*.002;
788 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
789 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
791 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
792 tipvelocity -= bounceness;
793 if (1 - friction * frictionness > 0)
794 tipvelocity *= 1 - friction * frictionness;
797 if (terrain.getOpacity(mid.x, mid.z) < .2)
798 tipvelocity += bounceness * elasticity * .3;
800 tipvelocity += bounceness * elasticity;
802 if (findLengthfast(&bounceness) > 1) {
804 if (terrain.getOpacity(mid.x, mid.z) > .2) {
806 whichsound = footstepsound3 + abs(Random() % 2);
808 whichsound = clank1sound + abs(Random() % 4);
810 whichsound = footstepsound + abs(Random() % 2);
812 emit_sound_at(whichsound, mid,
813 findLengthfast(&bounceness)
814 * (terrain.getOpacity(position.x, position.z) > .2
818 tippoint += (mid - oldmid) * 20;
821 velocity.y += gravity * multiplier;
822 tipvelocity.y += gravity * multiplier;
825 XYZ temppoint1, temppoint2;
828 temppoint1 = position;
829 temppoint2 = tippoint;
830 distance = findDistance(&temppoint1, &temppoint2);
831 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
832 rotation2 *= 360 / 6.28;
835 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
836 rotation1 *= 360 / 6.28;
843 if (temppoint1.x > temppoint2.x)
844 rotation1 = 360 - rotation1;
847 if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
848 freetime += multiplier;
858 multiplier = tempmult;
859 if (blooddrip && bloody) {
860 blooddripdelay -= blooddrip * multiplier / 2;
861 blooddrip -= multiplier;
866 if (blooddripdelay < 0 && bloodtoggle) {
870 bloodloc = position + (tippoint - position) * .7;
874 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
879 flamedelay -= multiplier;
880 if (onfire && flamedelay <= 0) {
882 flamedelay -= multiplier;
885 normalrot = Person::players[owner]->velocity;
889 if (Person::players[owner]->onterrain) {
893 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);
894 Sprite::setLastSpriteSpeed(4);
895 Sprite::setLastSpriteAlivetime(.3);
899 if (!onfire && owner == -1 && type != staff) {
900 flamedelay -= multiplier;
901 if (flamedelay <= 0) {
903 flamedelay -= multiplier;
905 if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
907 shinepoint = position + (tippoint - position) * (((float)abs(Random() % 100)) / 100);
908 Sprite::MakeSprite(weaponshinesprite, shinepoint, normalrot, 1, 1, 1, (.1 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3 * fast_sqrt(findDistance(&shinepoint, &viewer)), 1);
909 Sprite::setLastSpriteSpeed(4);
910 Sprite::setLastSpriteAlivetime(.3);
916 void Weapons::DoStuff()
920 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
921 weapon->DoStuff(i++);
927 static XYZ terrainlight;
928 static GLfloat M[16];
930 if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
931 distsq(&viewer, &position) < viewdistance * viewdistance)) {
935 if (velocity.x && !physics)
940 if (Person::players[owner]->occluded < 25)
941 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)
944 (Person::players[owner]->animTarget == knifeslashstartanim ||
945 Person::players[owner]->animTarget == swordsneakattackanim ||
946 (Person::players[owner]->animCurrent == staffhitanim && Person::players[owner]->frameCurrent > 1) ||
947 (Person::players[owner]->animCurrent == staffhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
948 (Person::players[owner]->animCurrent == staffspinhitanim && Person::players[owner]->frameCurrent > 1) ||
949 (Person::players[owner]->animCurrent == staffspinhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
950 (Person::players[owner]->animCurrent == staffgroundsmashanim && Person::players[owner]->frameCurrent > 1) ||
951 (Person::players[owner]->animTarget == swordslashanim && Person::players[owner]->frameTarget < 7) ||
952 Person::players[owner]->animTarget == crouchstabanim ||
953 Person::players[owner]->animTarget == swordslashreversalanim ||
954 Person::players[owner]->animTarget == swordslashreversedanim ||
955 Person::players[owner]->animTarget == knifefollowanim ||
956 Person::players[owner]->animTarget == swordgroundstabanim ||
957 Person::players[owner]->animTarget == knifethrowanim) &&
958 Person::players[owner]->animTarget == lastdrawnanim &&
959 !Person::players[owner]->skeleton.free
965 if (Person::players[owner]->animTarget == swordgroundstabanim) {
966 lastdrawnrotation1 = rotation1;
967 lastdrawnrotation2 = rotation2;
968 lastdrawnrotation3 = rotation3;
969 lastdrawnbigrotation = bigrotation;
970 lastdrawnbigtilt = bigtilt;
971 lastdrawnbigtilt2 = bigtilt2;
972 lastdrawnsmallrotation = smallrotation;
973 lastdrawnsmallrotation2 = smallrotation2;
977 terrainlight = terrain.getLighting(position.x, position.z);
978 if (drawhowmany > 0) {
979 glAlphaFunc(GL_GREATER, 0.01);
981 for (int j = drawhowmany; j > 0; j--) {
982 glMatrixMode(GL_MODELVIEW);
984 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
986 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));
988 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));
989 glRotatef(bigrotation * (((float)(j)) / drawhowmany) + lastdrawnbigrotation * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
990 glRotatef(bigtilt2 * (((float)(j)) / drawhowmany) + lastdrawnbigtilt2 * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
991 glRotatef(bigtilt * (((float)(j)) / drawhowmany) + lastdrawnbigtilt * (1 - ((float)(j)) / drawhowmany), 0, 0, 1);
992 glRotatef(-rotation1 * (((float)(j)) / drawhowmany) - lastdrawnrotation1 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 1, 0);
993 glRotatef(-rotation2 * (((float)(j)) / drawhowmany) - lastdrawnrotation2 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 0, 1);
994 glRotatef(-rotation3 * (((float)(j)) / drawhowmany) - lastdrawnrotation3 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
995 glRotatef(smallrotation * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
996 glRotatef(smallrotation2 * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation2 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
999 if (Person::players[owner]->animTarget == staffhitanim || Person::players[owner]->animCurrent == staffhitanim || Person::players[owner]->animTarget == staffhitreversedanim || Person::players[owner]->animCurrent == staffhitreversedanim) {
1000 glTranslatef(0, 0, -.3);
1002 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) {
1003 glTranslatef(0, 0, -.1);
1007 glEnable(GL_LIGHTING);
1010 if (!bloody || !bloodtoggle)
1011 throwingknifemodel.drawdifftex(knifetextureptr);
1014 throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1016 throwingknifemodel.drawdifftex(bloodknifetextureptr);
1020 if (!bloody || !bloodtoggle)
1021 swordmodel.drawdifftex(swordtextureptr);
1024 swordmodel.drawdifftex(lightbloodswordtextureptr);
1026 swordmodel.drawdifftex(bloodswordtextureptr);
1030 staffmodel.drawdifftex(stafftextureptr);
1037 lastdrawnposition = position;
1038 lastdrawntippoint = tippoint;
1039 lastdrawnrotation1 = rotation1;
1040 lastdrawnrotation2 = rotation2;
1041 lastdrawnrotation3 = rotation3;
1042 lastdrawnbigrotation = bigrotation;
1043 lastdrawnbigtilt = bigtilt;
1044 lastdrawnbigtilt2 = bigtilt2;
1045 lastdrawnsmallrotation = smallrotation;
1046 lastdrawnsmallrotation2 = smallrotation2;
1048 lastdrawnanim = Person::players[owner]->animCurrent;
1051 glMatrixMode(GL_MODELVIEW);
1054 glTranslatef(position.x, position.y - .02, position.z);
1055 glRotatef(bigrotation, 0, 1, 0);
1056 glRotatef(bigtilt2, 1, 0, 0);
1057 glRotatef(bigtilt, 0, 0, 1);
1058 glRotatef(-rotation1 + 90, 0, 1, 0);
1059 glRotatef(-rotation2 + 90, 0, 0, 1);
1060 glRotatef(-rotation3, 0, 1, 0);
1061 glRotatef(smallrotation, 1, 0, 0);
1062 glRotatef(smallrotation2, 0, 1, 0);
1063 glTranslatef(0, 0, length);
1064 glGetFloatv(GL_MODELVIEW_MATRIX, M);
1073 void Weapon::drop(XYZ v, XYZ tv, bool sethitsomething)
1079 if (sethitsomething) {
1087 void Weapon::thrown(XYZ v, bool sethitsomething)
1089 drop(v, v, sethitsomething);
1096 glAlphaFunc(GL_GREATER, 0.9);
1097 glEnable(GL_TEXTURE_2D);
1099 glEnable(GL_CULL_FACE);
1100 glCullFace(GL_FRONT);
1103 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
1115 Weapon::stafftextureptr.destroy();
1116 Weapon::knifetextureptr.destroy();
1117 Weapon::lightbloodknifetextureptr.destroy();
1118 Weapon::bloodknifetextureptr.destroy();
1119 Weapon::swordtextureptr.destroy();
1120 Weapon::lightbloodswordtextureptr.destroy();
1121 Weapon::bloodswordtextureptr.destroy();