2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 This file is part of Lugaru.
9 Lugaru is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 Lugaru is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
23 #include "Objects/Weapons.hpp"
25 #include "Animation/Animation.hpp"
26 #include "Audio/openal_wrapper.hpp"
27 #include "Audio/Sounds.hpp"
29 #include "Level/Awards.hpp"
30 #include "Tutorial.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern GLubyte bloodText[512 * 512 * 3];
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
52 extern int numthrowkill;
54 Model Weapon::throwingknifemodel;
55 Texture Weapon::knifetextureptr;
56 Texture Weapon::lightbloodknifetextureptr;
57 Texture Weapon::bloodknifetextureptr;
59 Model Weapon::swordmodel;
60 Texture Weapon::swordtextureptr;
61 Texture Weapon::lightbloodswordtextureptr;
62 Texture Weapon::bloodswordtextureptr;
64 Model Weapon::staffmodel;
65 Texture Weapon::stafftextureptr;
67 Weapon::Weapon(int t, int o) : owner(o)
80 void Weapon::setType(int t)
100 /* 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;
189 oldposition = position;
190 oldtippoint = tippoint;
191 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && !physics) { // if the weapon is flying
192 position += velocity * multiplier;
193 tippoint += velocity * multiplier;
194 whichpatchx = position.x / (terrain.size / subdivision * terrain.scale);
195 whichpatchz = position.z / (terrain.size / subdivision * terrain.scale);
196 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
197 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) { // if there are Object::objects where the weapon is
198 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) { // check for collision
199 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;
214 XYZ temppoint1, temppoint2;
218 temppoint2 = normalrot;
219 distance = findDistance(&temppoint1, &temppoint2);
220 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
221 rotation2 *= 360 / 6.28;
224 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
225 rotation1 *= 360 / 6.28;
226 if (temppoint1.x > temppoint2.x)
227 rotation1 = 360 - rotation1;
236 emit_sound_at(knifesheathesound, position, 128.);
240 Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
244 position -= velocity * multiplier;
245 tippoint -= velocity * multiplier;
246 tipvelocity = velocity;
253 if (velocity.x || velocity.y || velocity.z) {
254 for (unsigned j = 0; j < Person::players.size(); j++) {
256 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;
257 if (owner == -1 && distsqflat(&position, &Person::players[j]->coords) < 1.5 &&
258 distsq(&position, &Person::players[j]->coords) < 4 && Person::players[j]->weaponstuck == -1 &&
259 !Person::players[j]->skeleton.free && (int(j) != oldowner)) {
260 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) {
261 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)) ||
262 (Person::players[j]->creature == rabbittype && Random() % 2 == 0 && Person::players[j]->aitype == attacktypecutoff && Person::players[j]->weaponactive == -1)) {
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;
274 Person::players[j]->num_weapons++;
275 Person::players[j]->weaponstuck = Person::players[j]->num_weapons - 1;
276 if (normaldotproduct(Person::players[j]->facing, velocity) > 0)
277 Person::players[j]->weaponstuckwhere = 1;
279 Person::players[j]->weaponstuckwhere = 0;
281 Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
283 Person::players[j]->RagDoll(0);
284 Person::players[j]->jointVel(abdomen) += velocity * 2;
285 Person::players[j]->jointVel(neck) += velocity * 2;
286 Person::players[j]->jointVel(rightshoulder) += velocity * 2;
287 Person::players[j]->jointVel(leftshoulder) += velocity * 2;
288 if (bloodtoggle && !Tutorial::active)
289 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
290 if (Tutorial::active)
291 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
292 footvel = tippoint - position;
294 if (bloodtoggle && !Tutorial::active)
295 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
297 if (!Tutorial::active) {
298 if (Person::players[j]->weaponstuckwhere == 0)
299 Person::players[j]->DoBloodBig(2, 205);
300 if (Person::players[j]->weaponstuckwhere == 1)
301 Person::players[j]->DoBloodBig(2, 200);
302 Person::players[j]->damage += 200 / Person::players[j]->armorhigh;
303 Person::players[j]->deathbleeding = 1;
304 Person::players[j]->bloodloss += (200 + abs((float)(Random() % 40)) - 20) / Person::players[j]->armorhigh;
310 emit_sound_at(fleshstabsound, position, 128.);
312 if (Animation::animations[Person::players[0]->animTarget].height == highheight)
313 award_bonus(0, ninja);
315 award_bonus(0, Bullseyebonus);
323 if (position.y < terrain.getHeight(position.x, position.z)) {
324 if (terrain.getOpacity(position.x, position.z) < .2) {
326 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
327 position = colpoint * terrain.scale;
329 position.y = terrain.getHeight(position.x, position.z);
332 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
333 normalrot = terrain.getNormal(position.x, position.z) * -1;
335 glMatrixMode(GL_MODELVIEW);
339 glRotatef(bigrotation, 0, 1, 0);
340 glRotatef(bigtilt2, 1, 0, 0);
341 glRotatef(bigtilt, 0, 0, 1);
342 glRotatef(-rotation1 + 90, 0, 1, 0);
343 glRotatef(-rotation2 + 90, 0, 0, 1);
344 glRotatef(-rotation3, 0, 1, 0);
345 glRotatef(smallrotation, 1, 0, 0);
346 glRotatef(smallrotation2, 0, 1, 0);
347 glTranslatef(0, 0, 1);
348 glGetFloatv(GL_MODELVIEW_MATRIX, M);
353 position -= tippoint * .15;
354 XYZ temppoint1, temppoint2;
363 emit_sound_at(knifesheathesound, position, 128.);
366 terrainlight = terrain.getLighting(position.x, position.z);
367 if (environment == snowyenvironment) {
368 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
369 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
370 } else if (environment == grassyenvironment) {
371 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
372 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
373 } else if (environment == desertenvironment) {
374 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
375 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
382 position -= velocity * multiplier;
383 tippoint -= velocity * multiplier;
384 tipvelocity = velocity;
387 if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
388 velocity.y += gravity * multiplier;
390 XYZ temppoint1, temppoint2;
394 temppoint2 = velocity;
395 distance = findDistance(&temppoint1, &temppoint2);
396 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
397 rotation2 *= 360 / 6.28;
400 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
401 rotation1 *= 360 / 6.28;
408 if (temppoint1.x > temppoint2.x)
409 rotation1 = 360 - rotation1;
419 tempmult = multiplier;
421 for (int l = 0; l < 10; l++) {
422 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
424 position += velocity * multiplier;
425 tippoint += tipvelocity * multiplier;
428 midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
429 vel = tippoint - midp;
431 newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
432 newpoint2 = midp + vel * length * (mass / (mass + tipmass));
434 if (freetime > .04) {
435 velocity = velocity + (newpoint1 - position) / multiplier;
436 tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
439 position = newpoint1;
440 tippoint = newpoint2;
444 whichpatchx = (position.x) / (terrain.size / subdivision * terrain.scale);
445 whichpatchz = (position.z) / (terrain.size / subdivision * terrain.scale);
446 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision)
447 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) {
448 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
449 int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
453 start = tippoint - (position - tippoint) / 5;
454 end = position + (position - tippoint) / 30;
455 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
456 if (whichhit != -1) {
458 diff = (colpoint - position);
462 tippoint += (colpoint - position) + diff * .05;
463 position = colpoint + diff * .05;
464 oldtippoint = tippoint;
465 oldposition = tippoint;
468 start = position - (tippoint - position) / 5;
469 end = tippoint + (tippoint - position) / 30;
470 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
471 if (whichhit != -1) {
473 diff = (colpoint - tippoint);
477 position += (colpoint - tippoint) + diff * .05;
478 tippoint = colpoint + diff * .05;
479 oldposition = position;
480 oldtippoint = tippoint;
487 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
488 if (whichhit != -1) {
491 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
492 ReflectVector(&velocity, &terrainnormal);
493 position += terrainnormal * .002;
495 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
496 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
498 frictionness = abs(normaldotproduct(velocity, terrainnormal));
499 velocity -= bounceness;
500 if (1 - friction * frictionness > 0)
501 velocity *= 1 - friction * frictionness;
504 velocity += bounceness * elasticity;
506 if (findLengthfast(&bounceness) > 1) {
509 whichsound = footstepsound3 + abs(Random() % 2);
511 whichsound = clank1sound + abs(Random() % 4);
512 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
517 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
518 if (whichhit != -1) {
521 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
522 ReflectVector(&tipvelocity, &terrainnormal);
523 tippoint += terrainnormal * .002;
525 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
526 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
528 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
529 tipvelocity -= bounceness;
530 if (1 - friction * frictionness > 0)
531 tipvelocity *= 1 - friction * frictionness;
534 tipvelocity += bounceness * elasticity;
536 if (findLengthfast(&bounceness) > 1) {
539 whichsound = footstepsound3 + abs(Random() % 2);
541 whichsound = clank1sound + abs(Random() % 4);
542 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
546 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)
547 for (int m = 0; m < 2; m++) {
548 mid = (position * (21 + (float)m * 10) + tippoint * (19 - (float)m * 10)) / 40;
550 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
554 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
555 if (whichhit != -1) {
558 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
559 ReflectVector(&velocity, &terrainnormal);
561 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
562 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
564 frictionness = abs(normaldotproduct(velocity, terrainnormal));
565 velocity -= bounceness;
566 if (1 - friction * frictionness > 0)
567 velocity *= 1 - friction * frictionness;
570 velocity += bounceness * elasticity;
572 if (findLengthfast(&bounceness) > 1) {
575 whichsound = footstepsound3 + abs(Random() % 2);
577 whichsound = clank1sound + abs(Random() % 4);
578 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
580 position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
583 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
585 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
589 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
590 if (whichhit != -1) {
593 terrainnormal = DoRotation(Object::objects[k]->model.Triangles[whichhit].facenormal, 0, Object::objects[k]->yaw, 0) * -1;
594 ReflectVector(&tipvelocity, &terrainnormal);
596 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
597 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
599 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
600 tipvelocity -= bounceness;
601 if (1 - friction * frictionness > 0)
602 tipvelocity *= 1 - friction * frictionness;
605 tipvelocity += bounceness * elasticity;
607 if (findLengthfast(&bounceness) > 1) {
610 whichsound = footstepsound3 + abs(Random() % 2);
612 whichsound = clank1sound + abs(Random() % 4);
613 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
615 tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
621 whichhit = Object::objects[k]->model.LineCheck(&start, &end, &colpoint, &Object::objects[k]->position, &Object::objects[k]->yaw);
622 if (whichhit != -1) {
624 closestdistance = -1;
625 closestswordpoint = colpoint; //(position+tippoint)/2;
626 point[0] = DoRotation(Object::objects[k]->model.vertex[Object::objects[k]->model.Triangles[whichhit].vertex[0]], 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
627 point[1] = DoRotation(Object::objects[k]->model.vertex[Object::objects[k]->model.Triangles[whichhit].vertex[1]], 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
628 point[2] = DoRotation(Object::objects[k]->model.vertex[Object::objects[k]->model.Triangles[whichhit].vertex[2]], 0, Object::objects[k]->yaw, 0) + Object::objects[k]->position;
629 if (DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance, &colpoint )) {
630 if (distance < closestdistance || closestdistance == -1) {
631 closestpoint = colpoint;
632 closestdistance = distance;
635 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint )) {
636 if (distance < closestdistance || closestdistance == -1) {
637 closestpoint = colpoint;
638 closestdistance = distance;
641 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint )) {
642 if (distance < closestdistance || closestdistance == -1) {
643 closestpoint = colpoint;
644 closestdistance = distance;
647 if (closestdistance != -1 && isnormal(closestdistance)) {
648 if (DistancePointLine(&closestpoint, &position, &tippoint, &distance, &colpoint )) {
649 closestswordpoint = colpoint;
650 velocity += (closestpoint - closestswordpoint);
651 tipvelocity += (closestpoint - closestswordpoint);
652 position += (closestpoint - closestswordpoint);
653 tippoint += (closestpoint - closestswordpoint);
661 whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
662 if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
665 position = colpoint * terrain.scale;
667 position.y = terrain.getHeight(position.x, position.z);
669 terrainnormal = terrain.getNormal(position.x, position.z);
670 ReflectVector(&velocity, &terrainnormal);
671 position += terrainnormal * .002;
672 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
673 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
675 frictionness = abs(normaldotproduct(velocity, terrainnormal));
676 velocity -= bounceness;
677 if (1 - friction * frictionness > 0)
678 velocity *= 1 - friction * frictionness;
681 if (terrain.getOpacity(position.x, position.z) < .2)
682 velocity += bounceness * elasticity * .3;
684 velocity += bounceness * elasticity;
686 if (findLengthfast(&bounceness) > 1) {
688 if (terrain.getOpacity(position.x, position.z) > .2) {
690 whichsound = footstepsound3 + abs(Random() % 2);
692 whichsound = clank1sound + abs(Random() % 4);
694 whichsound = footstepsound + abs(Random() % 2);
696 emit_sound_at(whichsound, position,
697 findLengthfast(&bounceness)
698 * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
700 if (terrain.getOpacity(position.x, position.z) < .2) {
702 terrainlight = terrain.getLighting(position.x, position.z);
703 if (environment == snowyenvironment) {
704 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
705 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
706 } else if (environment == grassyenvironment) {
707 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
708 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
709 } else if (environment == desertenvironment) {
710 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
711 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
716 whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
717 if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
719 tippoint = colpoint * terrain.scale;
721 tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
723 terrainnormal = terrain.getNormal(tippoint.x, tippoint.z);
724 ReflectVector(&tipvelocity, &terrainnormal);
725 tippoint += terrainnormal * .002;
726 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
727 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
729 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
730 tipvelocity -= bounceness;
731 if (1 - friction * frictionness > 0)
732 tipvelocity *= 1 - friction * frictionness;
735 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2)
736 tipvelocity += bounceness * elasticity * .3;
738 tipvelocity += bounceness * elasticity;
740 if (findLengthfast(&bounceness) > 1) {
742 if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
744 whichsound = footstepsound3 + abs(Random() % 2);
746 whichsound = clank1sound + abs(Random() % 4);
748 whichsound = footstepsound + abs(Random() % 2);
750 emit_sound_at(whichsound, tippoint,
751 findLengthfast(&bounceness)
752 * (terrain.getOpacity(tippoint.x, tippoint.z) > .2 ? 128. : 32.));
754 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
756 terrainlight = terrain.getLighting(tippoint.x, tippoint.z);
757 if (environment == snowyenvironment) {
758 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
759 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
760 } else if (environment == grassyenvironment) {
761 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
762 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
763 } else if (environment == desertenvironment) {
764 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
765 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
772 mid = position + tippoint;
774 mid += (position - mid) / 20;
776 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
778 mid.y = terrain.getHeight(mid.x, mid.z);
780 terrainnormal = terrain.getNormal(mid.x, mid.z);
781 ReflectVector(&velocity, &terrainnormal);
782 //mid+=terrainnormal*.002;
783 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
784 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
786 frictionness = abs(normaldotproduct(velocity, terrainnormal));
787 velocity -= bounceness;
788 if (1 - friction * frictionness > 0)
789 velocity *= 1 - friction * frictionness;
792 if (terrain.getOpacity(mid.x, mid.z) < .2)
793 velocity += bounceness * elasticity * .3;
795 velocity += bounceness * elasticity;
797 if (findLengthfast(&bounceness) > 1) {
799 if (terrain.getOpacity(mid.x, mid.z) > .2) {
801 whichsound = footstepsound3 + abs(Random() % 2);
803 whichsound = clank1sound + abs(Random() % 4);
805 whichsound = footstepsound + abs(Random() % 2);
807 emit_sound_at(whichsound, mid,
808 findLengthfast(&bounceness)
809 * (terrain.getOpacity(position.x, position.z) > .2
813 position += (mid - oldmid) * 20;
816 mid = position + tippoint;
818 mid += (tippoint - mid) / 20;
820 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
822 mid.y = terrain.getHeight(mid.x, mid.z);
824 terrainnormal = terrain.getNormal(mid.x, mid.z);
825 ReflectVector(&tipvelocity, &terrainnormal);
826 //mid+=terrainnormal*.002;
827 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
828 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
830 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
831 tipvelocity -= bounceness;
832 if (1 - friction * frictionness > 0)
833 tipvelocity *= 1 - friction * frictionness;
836 if (terrain.getOpacity(mid.x, mid.z) < .2)
837 tipvelocity += bounceness * elasticity * .3;
839 tipvelocity += bounceness * elasticity;
841 if (findLengthfast(&bounceness) > 1) {
843 if (terrain.getOpacity(mid.x, mid.z) > .2) {
845 whichsound = footstepsound3 + abs(Random() % 2);
847 whichsound = clank1sound + abs(Random() % 4);
849 whichsound = footstepsound + abs(Random() % 2);
851 emit_sound_at(whichsound, mid,
852 findLengthfast(&bounceness)
853 * (terrain.getOpacity(position.x, position.z) > .2
857 tippoint += (mid - oldmid) * 20;
860 velocity.y += gravity * multiplier;
861 tipvelocity.y += gravity * multiplier;
864 XYZ temppoint1, temppoint2;
867 temppoint1 = position;
868 temppoint2 = tippoint;
869 distance = findDistance(&temppoint1, &temppoint2);
870 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
871 rotation2 *= 360 / 6.28;
874 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
875 rotation1 *= 360 / 6.28;
882 if (temppoint1.x > temppoint2.x)
883 rotation1 = 360 - rotation1;
886 if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
887 freetime += multiplier;
897 multiplier = tempmult;
898 if (blooddrip && bloody) {
899 blooddripdelay -= blooddrip * multiplier / 2;
900 blooddrip -= multiplier;
905 if (blooddripdelay < 0 && bloodtoggle) {
909 bloodloc = position + (tippoint - position) * .7;
913 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
918 flamedelay -= multiplier;
919 if (onfire && flamedelay <= 0) {
921 flamedelay -= multiplier;
924 normalrot = Person::players[owner]->velocity;
928 if (Person::players[owner]->onterrain) {
932 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);
933 Sprite::setLastSpriteSpeed(4);
934 Sprite::setLastSpriteAlivetime(.3);
938 if (!onfire && owner == -1 && type != staff) {
939 flamedelay -= multiplier;
940 if (flamedelay <= 0) {
942 flamedelay -= multiplier;
944 if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
946 shinepoint = position + (tippoint - position) * (((float)abs(Random() % 100)) / 100);
947 Sprite::MakeSprite(weaponshinesprite, shinepoint, normalrot, 1, 1, 1, (.1 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3 * fast_sqrt(findDistance(&shinepoint, &viewer)), 1);
948 Sprite::setLastSpriteSpeed(4);
949 Sprite::setLastSpriteAlivetime(.3);
955 void Weapons::DoStuff()
959 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
960 weapon->doStuff(i++);
966 static XYZ terrainlight;
967 static GLfloat M[16];
969 if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
970 distsq(&viewer, &position) < viewdistance * viewdistance)) {
974 if (velocity.x && !physics)
979 if (Person::players[owner]->occluded < 25)
980 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)
983 (Person::players[owner]->animTarget == knifeslashstartanim ||
984 Person::players[owner]->animTarget == swordsneakattackanim ||
985 (Person::players[owner]->animCurrent == staffhitanim && Person::players[owner]->frameCurrent > 1) ||
986 (Person::players[owner]->animCurrent == staffhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
987 (Person::players[owner]->animCurrent == staffspinhitanim && Person::players[owner]->frameCurrent > 1) ||
988 (Person::players[owner]->animCurrent == staffspinhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
989 (Person::players[owner]->animCurrent == staffgroundsmashanim && Person::players[owner]->frameCurrent > 1) ||
990 (Person::players[owner]->animTarget == swordslashanim && Person::players[owner]->frameTarget < 7) ||
991 Person::players[owner]->animTarget == crouchstabanim ||
992 Person::players[owner]->animTarget == swordslashreversalanim ||
993 Person::players[owner]->animTarget == swordslashreversedanim ||
994 Person::players[owner]->animTarget == knifefollowanim ||
995 Person::players[owner]->animTarget == swordgroundstabanim ||
996 Person::players[owner]->animTarget == knifethrowanim) &&
997 Person::players[owner]->animTarget == lastdrawnanim &&
998 !Person::players[owner]->skeleton.free
1004 if (Person::players[owner]->animTarget == swordgroundstabanim) {
1005 lastdrawnrotation1 = rotation1;
1006 lastdrawnrotation2 = rotation2;
1007 lastdrawnrotation3 = rotation3;
1008 lastdrawnbigrotation = bigrotation;
1009 lastdrawnbigtilt = bigtilt;
1010 lastdrawnbigtilt2 = bigtilt2;
1011 lastdrawnsmallrotation = smallrotation;
1012 lastdrawnsmallrotation2 = smallrotation2;
1016 terrainlight = terrain.getLighting(position.x, position.z);
1017 if (drawhowmany > 0) {
1018 glAlphaFunc(GL_GREATER, 0.01);
1020 for (int j = drawhowmany; j > 0; j--) {
1021 glMatrixMode(GL_MODELVIEW);
1023 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
1025 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));
1027 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));
1028 glRotatef(bigrotation * (((float)(j)) / drawhowmany) + lastdrawnbigrotation * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1029 glRotatef(bigtilt2 * (((float)(j)) / drawhowmany) + lastdrawnbigtilt2 * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
1030 glRotatef(bigtilt * (((float)(j)) / drawhowmany) + lastdrawnbigtilt * (1 - ((float)(j)) / drawhowmany), 0, 0, 1);
1031 glRotatef(-rotation1 * (((float)(j)) / drawhowmany) - lastdrawnrotation1 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 1, 0);
1032 glRotatef(-rotation2 * (((float)(j)) / drawhowmany) - lastdrawnrotation2 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 0, 1);
1033 glRotatef(-rotation3 * (((float)(j)) / drawhowmany) - lastdrawnrotation3 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1034 glRotatef(smallrotation * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
1035 glRotatef(smallrotation2 * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation2 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1038 if (Person::players[owner]->animTarget == staffhitanim || Person::players[owner]->animCurrent == staffhitanim || Person::players[owner]->animTarget == staffhitreversedanim || Person::players[owner]->animCurrent == staffhitreversedanim) {
1039 glTranslatef(0, 0, -.3);
1041 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) {
1042 glTranslatef(0, 0, -.1);
1046 glEnable(GL_LIGHTING);
1049 if (!bloody || !bloodtoggle)
1050 throwingknifemodel.drawdifftex(knifetextureptr);
1053 throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1055 throwingknifemodel.drawdifftex(bloodknifetextureptr);
1059 if (!bloody || !bloodtoggle)
1060 swordmodel.drawdifftex(swordtextureptr);
1063 swordmodel.drawdifftex(lightbloodswordtextureptr);
1065 swordmodel.drawdifftex(bloodswordtextureptr);
1069 staffmodel.drawdifftex(stafftextureptr);
1076 lastdrawnposition = position;
1077 lastdrawntippoint = tippoint;
1078 lastdrawnrotation1 = rotation1;
1079 lastdrawnrotation2 = rotation2;
1080 lastdrawnrotation3 = rotation3;
1081 lastdrawnbigrotation = bigrotation;
1082 lastdrawnbigtilt = bigtilt;
1083 lastdrawnbigtilt2 = bigtilt2;
1084 lastdrawnsmallrotation = smallrotation;
1085 lastdrawnsmallrotation2 = smallrotation2;
1087 lastdrawnanim = Person::players[owner]->animCurrent;
1090 glMatrixMode(GL_MODELVIEW);
1093 glTranslatef(position.x, position.y - .02, position.z);
1094 glRotatef(bigrotation, 0, 1, 0);
1095 glRotatef(bigtilt2, 1, 0, 0);
1096 glRotatef(bigtilt, 0, 0, 1);
1097 glRotatef(-rotation1 + 90, 0, 1, 0);
1098 glRotatef(-rotation2 + 90, 0, 0, 1);
1099 glRotatef(-rotation3, 0, 1, 0);
1100 glRotatef(smallrotation, 1, 0, 0);
1101 glRotatef(smallrotation2, 0, 1, 0);
1102 glTranslatef(0, 0, length);
1103 glGetFloatv(GL_MODELVIEW_MATRIX, M);
1112 void Weapon::drop(XYZ v, XYZ tv, bool sethitsomething)
1118 if (sethitsomething) {
1126 void Weapon::thrown(XYZ v, bool sethitsomething)
1128 drop(v, v, sethitsomething);
1135 glAlphaFunc(GL_GREATER, 0.9);
1136 glEnable(GL_TEXTURE_2D);
1138 glEnable(GL_CULL_FACE);
1139 glCullFace(GL_FRONT);
1142 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {