2 Copyright (C) 2003, 2010 - Wolfire Games
4 This file is part of Lugaru.
6 This file is part of Lugaru.
8 Lugaru is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 Lugaru is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
22 /**> HEADER FILES <**/
24 #include "openal_wrapper.h"
25 #include "Animation.h"
30 extern float multiplier;
31 extern Terrain terrain;
33 extern int environment;
35 extern FRUSTUM frustum;
37 extern float realmultiplier;
39 extern float slomodelay;
40 extern bool cellophane;
41 extern float texdetail;
42 extern GLubyte bloodText[512 * 512 * 3];
43 extern int bloodtoggle;
44 extern Objects objects;
45 extern bool autoslomo;
46 extern float camerashake;
48 extern float viewdistance;
49 extern float blackout;
50 extern int difficulty;
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 XYZ extramove;
120 static float tempmult;
125 if (damage >= 2 && type == staff && owner != -1) { // the staff breaks
126 emit_sound_at(staffbreaksound, tippoint);
128 for (int j = 0; j < 40; j++) {
129 tempvel.x = float(abs(Random() % 100) - 50) / 20;
130 tempvel.y = float(abs(Random() % 100) - 50) / 20;
131 tempvel.z = float(abs(Random() % 100) - 50) / 20;
132 Sprite::MakeSprite(splintersprite, position + (tippoint - position) * ((float)j - 8) / 32, tempvel * .5, 115 / 255, 73 / 255, 12 / 255, .1, 1);
135 Person::players[owner]->weaponactive = -1;
136 Person::players[owner]->num_weapons--;
137 if (Person::players[owner]->num_weapons) {
138 Person::players[owner]->weaponids[0] = Person::players[owner]->weaponids[Person::players[owner]->num_weapons];
139 if (Person::players[owner]->weaponstuck == Person::players[owner]->num_weapons)
140 Person::players[owner]->weaponstuck = 0;
151 oldposition = position;
152 oldtippoint = tippoint;
153 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && !physics) { // if the weapon is flying
154 position += velocity * multiplier;
155 tippoint += velocity * multiplier;
156 whichpatchx = position.x / (terrain.size / subdivision * terrain.scale);
157 whichpatchz = position.z / (terrain.size / subdivision * terrain.scale);
158 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
159 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) { // if there are objects where the weapon is
160 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) { // check for collision
161 int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
164 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
165 if (whichhit != -1) {
166 if (objects.type[k] == treetrunktype) {
167 objects.model[k].MakeDecal(breakdecal, DoRotation(colpoint - objects.position[k], 0, -objects.yaw[k], 0), .1, 1, Random() % 360);
168 normalrot = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0);
171 position = colpoint - normalrot * .1;
172 else if (type == sword)
173 position = colpoint - normalrot * .2;
174 else if (type == staff)
175 position = colpoint - normalrot * .2;
176 XYZ temppoint1, temppoint2, tempforward;
180 temppoint2 = normalrot;
181 distance = findDistance(&temppoint1, &temppoint2);
182 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
183 rotation2 *= 360 / 6.28;
186 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
187 rotation1 *= 360 / 6.28;
188 if (temppoint1.x > temppoint2.x)
189 rotation1 = 360 - rotation1;
198 emit_sound_at(knifesheathesound, position, 128.);
202 Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
206 position -= velocity * multiplier;
207 tippoint -= velocity * multiplier;
208 tipvelocity = velocity;
215 if (velocity.x || velocity.y || velocity.z) {
216 for (unsigned j = 0; j < Person::players.size(); j++) {
218 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;
219 if (owner == -1 && distsqflat(&position, &Person::players[j]->coords) < 1.5 &&
220 distsq(&position, &Person::players[j]->coords) < 4 && Person::players[j]->weaponstuck == -1 &&
221 !Person::players[j]->skeleton.free && (int(j) != oldowner)) {
222 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) {
223 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)) ||
224 (Person::players[j]->creature == rabbittype && Random() % 2 == 0 && Person::players[j]->aitype == attacktypecutoff && Person::players[j]->weaponactive == -1)) {
225 emit_sound_at(knifedrawsound, Person::players[j]->coords, 128.);
227 Person::players[j]->weaponactive = 0;
228 Person::players[j]->animTarget = removeknifeanim;
229 Person::players[j]->frameTarget = 1;
230 Person::players[j]->target = 1;
231 owner = Person::players[j]->id;
232 if (Person::players[j]->num_weapons > 0) {
233 Person::players[j]->weaponids[Person::players[j]->num_weapons] = Person::players[j]->weaponids[0];
235 Person::players[j]->num_weapons++;
236 Person::players[j]->weaponids[0] = i;
238 Person::players[j]->aitype = attacktypecutoff;
242 Person::players[j]->num_weapons++;
243 Person::players[j]->weaponstuck = Person::players[j]->num_weapons - 1;
244 if (normaldotproduct(Person::players[j]->facing, velocity) > 0)
245 Person::players[j]->weaponstuckwhere = 1;
247 Person::players[j]->weaponstuckwhere = 0;
249 Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
251 Person::players[j]->RagDoll(0);
252 Person::players[j]->jointVel(abdomen) += velocity * 2;
253 Person::players[j]->jointVel(neck) += velocity * 2;
254 Person::players[j]->jointVel(rightshoulder) += velocity * 2;
255 Person::players[j]->jointVel(leftshoulder) += velocity * 2;
256 if (bloodtoggle && tutoriallevel != 1)
257 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
258 if (tutoriallevel == 1)
259 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
260 footvel = tippoint - position;
262 if (bloodtoggle && tutoriallevel != 1)
263 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
265 if (tutoriallevel != 1) {
266 if (Person::players[j]->weaponstuckwhere == 0)
267 Person::players[j]->DoBloodBig(2, 205);
268 if (Person::players[j]->weaponstuckwhere == 1)
269 Person::players[j]->DoBloodBig(2, 200);
270 Person::players[j]->damage += 200 / Person::players[j]->armorhigh;
271 Person::players[j]->deathbleeding = 1;
272 Person::players[j]->bloodloss += (200 + abs((float)(Random() % 40)) - 20) / Person::players[j]->armorhigh;
278 emit_sound_at(fleshstabsound, position, 128.);
280 if (animation[Person::players[0]->animTarget].height == highheight)
281 award_bonus(0, ninja);
283 award_bonus(0, Bullseyebonus);
291 if (position.y < terrain.getHeight(position.x, position.z)) {
292 if (terrain.getOpacity(position.x, position.z) < .2) {
294 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
295 position = colpoint * terrain.scale;
297 position.y = terrain.getHeight(position.x, position.z);
300 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
301 normalrot = terrain.getNormal(position.x, position.z) * -1;
303 glMatrixMode(GL_MODELVIEW);
307 glRotatef(bigrotation, 0, 1, 0);
308 glRotatef(bigtilt2, 1, 0, 0);
309 glRotatef(bigtilt, 0, 0, 1);
310 glRotatef(-rotation1 + 90, 0, 1, 0);
311 glRotatef(-rotation2 + 90, 0, 0, 1);
312 glRotatef(-rotation3, 0, 1, 0);
313 glRotatef(smallrotation, 1, 0, 0);
314 glRotatef(smallrotation2, 0, 1, 0);
315 glTranslatef(0, 0, 1);
316 glGetFloatv(GL_MODELVIEW_MATRIX, M);
321 position -= tippoint * .15;
322 XYZ temppoint1, temppoint2, tempforward;
331 emit_sound_at(knifesheathesound, position, 128.);
334 terrainlight = terrain.getLighting(position.x, position.z);
335 if (environment == snowyenvironment) {
336 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
337 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
338 } else if (environment == grassyenvironment) {
339 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
340 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
341 } else if (environment == desertenvironment) {
342 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
343 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
350 position -= velocity * multiplier;
351 tippoint -= velocity * multiplier;
352 tipvelocity = velocity;
355 if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
356 velocity.y += gravity * multiplier;
358 XYZ temppoint1, temppoint2, tempforward;
362 temppoint2 = velocity;
363 distance = findDistance(&temppoint1, &temppoint2);
364 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
365 rotation2 *= 360 / 6.28;
368 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
369 rotation1 *= 360 / 6.28;
376 if (temppoint1.x > temppoint2.x)
377 rotation1 = 360 - rotation1;
387 tempmult = multiplier;
389 for (int l = 0; l < 10; l++) {
390 if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
392 position += velocity * multiplier;
393 tippoint += tipvelocity * multiplier;
396 midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
397 vel = tippoint - midp;
399 newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
400 newpoint2 = midp + vel * length * (mass / (mass + tipmass));
402 if (freetime > .04) {
403 velocity = velocity + (newpoint1 - position) / multiplier;
404 tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
407 position = newpoint1;
408 tippoint = newpoint2;
412 whichpatchx = (position.x) / (terrain.size / subdivision * terrain.scale);
413 whichpatchz = (position.z) / (terrain.size / subdivision * terrain.scale);
414 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision)
415 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) {
416 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
417 int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
421 start = tippoint - (position - tippoint) / 5;
422 end = position + (position - tippoint) / 30;
423 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
424 if (whichhit != -1) {
426 diff = (colpoint - position);
430 tippoint += (colpoint - position) + diff * .05;
431 position = colpoint + diff * .05;
432 oldtippoint = tippoint;
433 oldposition = tippoint;
436 start = position - (tippoint - position) / 5;
437 end = tippoint + (tippoint - position) / 30;
438 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
439 if (whichhit != -1) {
441 diff = (colpoint - tippoint);
445 position += (colpoint - tippoint) + diff * .05;
446 tippoint = colpoint + diff * .05;
447 oldposition = position;
448 oldtippoint = tippoint;
455 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
456 if (whichhit != -1) {
459 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
460 ReflectVector(&velocity, &terrainnormal);
461 position += terrainnormal * .002;
463 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
464 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
466 frictionness = abs(normaldotproduct(velocity, terrainnormal));
467 velocity -= bounceness;
468 if (1 - friction * frictionness > 0)
469 velocity *= 1 - friction * frictionness;
472 velocity += bounceness * elasticity;
474 if (findLengthfast(&bounceness) > 1) {
477 whichsound = footstepsound3 + abs(Random() % 2);
479 whichsound = clank1sound + abs(Random() % 4);
480 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
485 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
486 if (whichhit != -1) {
489 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
490 ReflectVector(&tipvelocity, &terrainnormal);
491 tippoint += terrainnormal * .002;
493 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
494 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
496 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
497 tipvelocity -= bounceness;
498 if (1 - friction * frictionness > 0)
499 tipvelocity *= 1 - friction * frictionness;
502 tipvelocity += bounceness * elasticity;
504 if (findLengthfast(&bounceness) > 1) {
507 whichsound = footstepsound3 + abs(Random() % 2);
509 whichsound = clank1sound + abs(Random() % 4);
510 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
514 if ((objects.type[k] != boxtype && objects.type[k] != platformtype && objects.type[k] != walltype && objects.type[k] != weirdtype) || objects.pitch[k] != 0)
515 for (int m = 0; m < 2; m++) {
516 mid = (position * (21 + (float)m * 10) + tippoint * (19 - (float)m * 10)) / 40;
518 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
522 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
523 if (whichhit != -1) {
526 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
527 ReflectVector(&velocity, &terrainnormal);
529 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
530 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
532 frictionness = abs(normaldotproduct(velocity, terrainnormal));
533 velocity -= bounceness;
534 if (1 - friction * frictionness > 0)
535 velocity *= 1 - friction * frictionness;
538 velocity += bounceness * elasticity;
540 if (findLengthfast(&bounceness) > 1) {
543 whichsound = footstepsound3 + abs(Random() % 2);
545 whichsound = clank1sound + abs(Random() % 4);
546 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
548 position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
551 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
553 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
557 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
558 if (whichhit != -1) {
561 terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
562 ReflectVector(&tipvelocity, &terrainnormal);
564 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
565 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
567 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
568 tipvelocity -= bounceness;
569 if (1 - friction * frictionness > 0)
570 tipvelocity *= 1 - friction * frictionness;
573 tipvelocity += bounceness * elasticity;
575 if (findLengthfast(&bounceness) > 1) {
578 whichsound = footstepsound3 + abs(Random() % 2);
580 whichsound = clank1sound + abs(Random() % 4);
581 emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
583 tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
589 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
590 if (whichhit != -1) {
592 closestdistance = -1;
593 closestswordpoint = colpoint; //(position+tippoint)/2;
594 point[0] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[0]], 0, objects.yaw[k], 0) + objects.position[k];
595 point[1] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[1]], 0, objects.yaw[k], 0) + objects.position[k];
596 point[2] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[2]], 0, objects.yaw[k], 0) + objects.position[k];
597 if (DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance, &colpoint )) {
598 if (distance < closestdistance || closestdistance == -1) {
599 closestpoint = colpoint;
600 closestdistance = distance;
603 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint )) {
604 if (distance < closestdistance || closestdistance == -1) {
605 closestpoint = colpoint;
606 closestdistance = distance;
609 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint )) {
610 if (distance < closestdistance || closestdistance == -1) {
611 closestpoint = colpoint;
612 closestdistance = distance;
615 if (closestdistance != -1 && isnormal(closestdistance)) {
616 if (DistancePointLine(&closestpoint, &position, &tippoint, &distance, &colpoint )) {
617 closestswordpoint = colpoint;
618 velocity += (closestpoint - closestswordpoint);
619 tipvelocity += (closestpoint - closestswordpoint);
620 position += (closestpoint - closestswordpoint);
621 tippoint += (closestpoint - closestswordpoint);
629 whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
630 if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
633 position = colpoint * terrain.scale;
635 position.y = terrain.getHeight(position.x, position.z);
637 terrainnormal = terrain.getNormal(position.x, position.z);
638 ReflectVector(&velocity, &terrainnormal);
639 position += terrainnormal * .002;
640 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
641 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
643 frictionness = abs(normaldotproduct(velocity, terrainnormal));
644 velocity -= bounceness;
645 if (1 - friction * frictionness > 0)
646 velocity *= 1 - friction * frictionness;
649 if (terrain.getOpacity(position.x, position.z) < .2)
650 velocity += bounceness * elasticity * .3;
652 velocity += bounceness * elasticity;
654 if (findLengthfast(&bounceness) > 1) {
656 if (terrain.getOpacity(position.x, position.z) > .2) {
658 whichsound = footstepsound3 + abs(Random() % 2);
660 whichsound = clank1sound + abs(Random() % 4);
662 whichsound = footstepsound + abs(Random() % 2);
664 emit_sound_at(whichsound, position,
665 findLengthfast(&bounceness)
666 * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
668 if (terrain.getOpacity(position.x, position.z) < .2) {
670 terrainlight = terrain.getLighting(position.x, position.z);
671 if (environment == snowyenvironment) {
672 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
673 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
674 } else if (environment == grassyenvironment) {
675 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
676 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
677 } else if (environment == desertenvironment) {
678 if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
679 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
684 whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
685 if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
687 tippoint = colpoint * terrain.scale;
689 tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
691 terrainnormal = terrain.getNormal(tippoint.x, tippoint.z);
692 ReflectVector(&tipvelocity, &terrainnormal);
693 tippoint += terrainnormal * .002;
694 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
695 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
697 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
698 tipvelocity -= bounceness;
699 if (1 - friction * frictionness > 0)
700 tipvelocity *= 1 - friction * frictionness;
703 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2)
704 tipvelocity += bounceness * elasticity * .3;
706 tipvelocity += bounceness * elasticity;
708 if (findLengthfast(&bounceness) > 1) {
710 if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
712 whichsound = footstepsound3 + abs(Random() % 2);
714 whichsound = clank1sound + abs(Random() % 4);
716 whichsound = footstepsound + abs(Random() % 2);
718 emit_sound_at(whichsound, tippoint,
719 findLengthfast(&bounceness)
720 * (terrain.getOpacity(tippoint.x, tippoint.z) > .2 ? 128. : 32.));
722 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
724 terrainlight = terrain.getLighting(tippoint.x, tippoint.z);
725 if (environment == snowyenvironment) {
726 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
727 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
728 } else if (environment == grassyenvironment) {
729 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
730 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
731 } else if (environment == desertenvironment) {
732 if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
733 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
740 mid = position + tippoint;
742 mid += (position - mid) / 20;
744 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
746 mid.y = terrain.getHeight(mid.x, mid.z);
748 terrainnormal = terrain.getNormal(mid.x, mid.z);
749 ReflectVector(&velocity, &terrainnormal);
750 //mid+=terrainnormal*.002;
751 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
752 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
754 frictionness = abs(normaldotproduct(velocity, terrainnormal));
755 velocity -= bounceness;
756 if (1 - friction * frictionness > 0)
757 velocity *= 1 - friction * frictionness;
760 if (terrain.getOpacity(mid.x, mid.z) < .2)
761 velocity += bounceness * elasticity * .3;
763 velocity += bounceness * elasticity;
765 if (findLengthfast(&bounceness) > 1) {
767 if (terrain.getOpacity(mid.x, mid.z) > .2) {
769 whichsound = footstepsound3 + abs(Random() % 2);
771 whichsound = clank1sound + abs(Random() % 4);
773 whichsound = footstepsound + abs(Random() % 2);
775 emit_sound_at(whichsound, mid,
776 findLengthfast(&bounceness)
777 * (terrain.getOpacity(position.x, position.z) > .2
781 position += (mid - oldmid) * 20;
784 mid = position + tippoint;
786 mid += (tippoint - mid) / 20;
788 if (mid.y < terrain.getHeight(mid.x, mid.z)) {
790 mid.y = terrain.getHeight(mid.x, mid.z);
792 terrainnormal = terrain.getNormal(mid.x, mid.z);
793 ReflectVector(&tipvelocity, &terrainnormal);
794 //mid+=terrainnormal*.002;
795 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
796 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
798 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
799 tipvelocity -= bounceness;
800 if (1 - friction * frictionness > 0)
801 tipvelocity *= 1 - friction * frictionness;
804 if (terrain.getOpacity(mid.x, mid.z) < .2)
805 tipvelocity += bounceness * elasticity * .3;
807 tipvelocity += bounceness * elasticity;
809 if (findLengthfast(&bounceness) > 1) {
811 if (terrain.getOpacity(mid.x, mid.z) > .2) {
813 whichsound = footstepsound3 + abs(Random() % 2);
815 whichsound = clank1sound + abs(Random() % 4);
817 whichsound = footstepsound + abs(Random() % 2);
819 emit_sound_at(whichsound, mid,
820 findLengthfast(&bounceness)
821 * (terrain.getOpacity(position.x, position.z) > .2
825 tippoint += (mid - oldmid) * 20;
828 velocity.y += gravity * multiplier;
829 tipvelocity.y += gravity * multiplier;
832 XYZ temppoint1, temppoint2, tempforward;
835 temppoint1 = position;
836 temppoint2 = tippoint;
837 distance = findDistance(&temppoint1, &temppoint2);
838 rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
839 rotation2 *= 360 / 6.28;
842 rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
843 rotation1 *= 360 / 6.28;
850 if (temppoint1.x > temppoint2.x)
851 rotation1 = 360 - rotation1;
854 if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
855 freetime += multiplier;
865 multiplier = tempmult;
866 if (blooddrip && bloody) {
867 blooddripdelay -= blooddrip * multiplier / 2;
868 blooddrip -= multiplier;
873 if (blooddripdelay < 0 && bloodtoggle) {
877 bloodloc = position + (tippoint - position) * .7;
881 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
886 flamedelay -= multiplier;
887 if (onfire && flamedelay <= 0) {
889 flamedelay -= multiplier;
892 normalrot = Person::players[owner]->velocity;
896 if (Person::players[owner]->onterrain) {
900 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);
901 Sprite::setLastSpriteSpeed(4);
902 Sprite::setLastSpriteAlivetime(.3);
906 if (!onfire && owner == -1 && type != staff) {
907 flamedelay -= multiplier;
908 if (flamedelay <= 0) {
910 flamedelay -= multiplier;
912 if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
914 shinepoint = position + (tippoint - position) * (((float)abs(Random() % 100)) / 100);
915 Sprite::MakeSprite(weaponshinesprite, shinepoint, normalrot, 1, 1, 1, (.1 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3 * fast_sqrt(findDistance(&shinepoint, &viewer)), 1);
916 Sprite::setLastSpriteSpeed(4);
917 Sprite::setLastSpriteAlivetime(.3);
923 void Weapons::DoStuff()
927 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
928 weapon->DoStuff(i++);
934 static XYZ terrainlight;
935 static GLfloat M[16];
937 if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
938 distsq(&viewer, &position) < viewdistance * viewdistance)) {
942 if (velocity.x && !physics)
947 if (Person::players[owner]->occluded < 25)
948 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)
951 (Person::players[owner]->animTarget == knifeslashstartanim ||
952 Person::players[owner]->animTarget == swordsneakattackanim ||
953 (Person::players[owner]->animCurrent == staffhitanim && Person::players[owner]->frameCurrent > 1) ||
954 (Person::players[owner]->animCurrent == staffhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
955 (Person::players[owner]->animCurrent == staffspinhitanim && Person::players[owner]->frameCurrent > 1) ||
956 (Person::players[owner]->animCurrent == staffspinhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
957 (Person::players[owner]->animCurrent == staffgroundsmashanim && Person::players[owner]->frameCurrent > 1) ||
958 (Person::players[owner]->animTarget == swordslashanim && Person::players[owner]->frameTarget < 7) ||
959 Person::players[owner]->animTarget == crouchstabanim ||
960 Person::players[owner]->animTarget == swordslashreversalanim ||
961 Person::players[owner]->animTarget == swordslashreversedanim ||
962 Person::players[owner]->animTarget == knifefollowanim ||
963 Person::players[owner]->animTarget == swordgroundstabanim ||
964 Person::players[owner]->animTarget == knifethrowanim) &&
965 Person::players[owner]->animTarget == lastdrawnanim &&
966 !Person::players[owner]->skeleton.free
972 if (Person::players[owner]->animTarget == swordgroundstabanim) {
973 lastdrawnrotation1 = rotation1;
974 lastdrawnrotation2 = rotation2;
975 lastdrawnrotation3 = rotation3;
976 lastdrawnbigrotation = bigrotation;
977 lastdrawnbigtilt = bigtilt;
978 lastdrawnbigtilt2 = bigtilt2;
979 lastdrawnsmallrotation = smallrotation;
980 lastdrawnsmallrotation2 = smallrotation2;
984 terrainlight = terrain.getLighting(position.x, position.z);
985 if (drawhowmany > 0) {
986 glAlphaFunc(GL_GREATER, 0.01);
988 for (int j = drawhowmany; j > 0; j--) {
989 glMatrixMode(GL_MODELVIEW);
991 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
993 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));
995 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));
996 glRotatef(bigrotation * (((float)(j)) / drawhowmany) + lastdrawnbigrotation * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
997 glRotatef(bigtilt2 * (((float)(j)) / drawhowmany) + lastdrawnbigtilt2 * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
998 glRotatef(bigtilt * (((float)(j)) / drawhowmany) + lastdrawnbigtilt * (1 - ((float)(j)) / drawhowmany), 0, 0, 1);
999 glRotatef(-rotation1 * (((float)(j)) / drawhowmany) - lastdrawnrotation1 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 1, 0);
1000 glRotatef(-rotation2 * (((float)(j)) / drawhowmany) - lastdrawnrotation2 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 0, 1);
1001 glRotatef(-rotation3 * (((float)(j)) / drawhowmany) - lastdrawnrotation3 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1002 glRotatef(smallrotation * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
1003 glRotatef(smallrotation2 * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation2 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
1006 if (Person::players[owner]->animTarget == staffhitanim || Person::players[owner]->animCurrent == staffhitanim || Person::players[owner]->animTarget == staffhitreversedanim || Person::players[owner]->animCurrent == staffhitreversedanim) {
1007 glTranslatef(0, 0, -.3);
1009 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) {
1010 glTranslatef(0, 0, -.1);
1014 glEnable(GL_LIGHTING);
1017 if (!bloody || !bloodtoggle)
1018 throwingknifemodel.drawdifftex(knifetextureptr);
1021 throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1023 throwingknifemodel.drawdifftex(bloodknifetextureptr);
1027 if (!bloody || !bloodtoggle)
1028 swordmodel.drawdifftex(swordtextureptr);
1031 swordmodel.drawdifftex(lightbloodswordtextureptr);
1033 swordmodel.drawdifftex(bloodswordtextureptr);
1037 staffmodel.drawdifftex(stafftextureptr);
1044 lastdrawnposition = position;
1045 lastdrawntippoint = tippoint;
1046 lastdrawnrotation1 = rotation1;
1047 lastdrawnrotation2 = rotation2;
1048 lastdrawnrotation3 = rotation3;
1049 lastdrawnbigrotation = bigrotation;
1050 lastdrawnbigtilt = bigtilt;
1051 lastdrawnbigtilt2 = bigtilt2;
1052 lastdrawnsmallrotation = smallrotation;
1053 lastdrawnsmallrotation2 = smallrotation2;
1055 lastdrawnanim = Person::players[owner]->animCurrent;
1058 glMatrixMode(GL_MODELVIEW);
1061 glTranslatef(position.x, position.y - .02, position.z);
1062 glRotatef(bigrotation, 0, 1, 0);
1063 glRotatef(bigtilt2, 1, 0, 0);
1064 glRotatef(bigtilt, 0, 0, 1);
1065 glRotatef(-rotation1 + 90, 0, 1, 0);
1066 glRotatef(-rotation2 + 90, 0, 0, 1);
1067 glRotatef(-rotation3, 0, 1, 0);
1068 glRotatef(smallrotation, 1, 0, 0);
1069 glRotatef(smallrotation2, 0, 1, 0);
1070 glTranslatef(0, 0, length);
1071 glGetFloatv(GL_MODELVIEW_MATRIX, M);
1082 glAlphaFunc(GL_GREATER, 0.9);
1083 glEnable(GL_TEXTURE_2D);
1085 glEnable(GL_CULL_FACE);
1086 glCullFace(GL_FRONT);
1089 for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
1101 Weapon::stafftextureptr.destroy();
1102 Weapon::knifetextureptr.destroy();
1103 Weapon::lightbloodknifetextureptr.destroy();
1104 Weapon::bloodknifetextureptr.destroy();
1105 Weapon::swordtextureptr.destroy();
1106 Weapon::lightbloodswordtextureptr.destroy();
1107 Weapon::bloodswordtextureptr.destroy();