]> git.jsancho.org Git - lugaru.git/blob - Source/Weapons.cpp
b8784587613e13ae5b11ceee8f2a61bf38a8ab4b
[lugaru.git] / Source / Weapons.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 This file is part of Lugaru.
7
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.
12
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.
17
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/>.
20 */
21
22 /**> HEADER FILES <**/
23 #include "Weapons.h"
24 #include "openal_wrapper.h"
25 #include "Animation.h"
26 #include "Sounds.h"
27 #include "Game.h"
28 #include "Awards.h"
29
30 extern float multiplier;
31 extern Terrain terrain;
32 extern float gravity;
33 extern int environment;
34 extern int detail;
35 extern FRUSTUM frustum;
36 extern XYZ viewer;
37 extern float realmultiplier;
38 extern int slomo;
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;
47 extern float woozy;
48 extern float viewdistance;
49 extern float blackout;
50 extern int difficulty;
51 extern bool freeze;
52 extern int tutoriallevel;
53 extern int numthrowkill;
54
55 Model Weapon::throwingknifemodel;
56 Texture Weapon::knifetextureptr;
57 Texture Weapon::lightbloodknifetextureptr;
58 Texture Weapon::bloodknifetextureptr;
59
60 Model Weapon::swordmodel;
61 Texture Weapon::swordtextureptr;
62 Texture Weapon::lightbloodswordtextureptr;
63 Texture Weapon::bloodswordtextureptr;
64
65 Model Weapon::staffmodel;
66 Texture Weapon::stafftextureptr;
67
68 Weapon::Weapon(int t, int o) : owner(o)
69 {
70     setType(t);
71     bloody = 0;
72     blooddrip = 0;
73     blooddripdelay = 0;
74     onfire = 0;
75     flamedelay = 0;
76     damage = 0;
77     position = -1000;
78     tippoint = -1000;
79 }
80
81 void Weapon::setType(int t)
82 {
83     type = t;
84     if (type == sword) {
85         mass = 1.5;
86         tipmass = 1;
87         length = .8;
88     }
89     if (type == staff) {
90         mass = 2;
91         tipmass = 1;
92         length = 1.5;
93     }
94     if (type == knife) {
95         mass = 1;
96         tipmass = 1.2;
97         length = .25;
98     }
99 }
100
101 void Weapon::DoStuff(int i)
102 {
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;
107     static XYZ vel;
108     static XYZ midp;
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;
116     static XYZ point[3];
117     static XYZ closestpoint;
118     static XYZ closestswordpoint;
119     static XYZ extramove;
120     static float tempmult;
121
122     if (owner != -1) {
123         oldowner = owner;
124     }
125     if (damage >= 2 && type == staff && owner != -1) { // the staff breaks
126         emit_sound_at(staffbreaksound, tippoint);
127         XYZ tempvel;
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);
133         }
134         if (owner != -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;
141             }
142         }
143         owner = -1;
144         hitsomething = 0;
145         missed = 1;
146         freetime = 0;
147         firstfree = 1;
148         position = 0;
149         physics = 0;
150     }
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];
162                     start = oldtippoint;
163                     end = tippoint;
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);
169                             velocity = 0;
170                             if (type == knife)
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;
177                             float distance;
178
179                             temppoint1 = 0;
180                             temppoint2 = normalrot;
181                             distance = findDistance(&temppoint1, &temppoint2);
182                             rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
183                             rotation2 *= 360 / 6.28;
184                             temppoint1.y = 0;
185                             temppoint2.y = 0;
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;
190
191                             rotation3 = 0;
192                             smallrotation = 90;
193                             smallrotation2 = 0;
194                             bigtilt = 0;
195                             bigtilt2 = 0;
196                             bigrotation = 0;
197
198                             emit_sound_at(knifesheathesound, position, 128.);
199
200                             bloody = 0;
201
202                             Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
203                         } else {
204                             physics = 1;
205                             firstfree = 1;
206                             position -= velocity * multiplier;
207                             tippoint -= velocity * multiplier;
208                             tipvelocity = velocity;
209                         }
210                     }
211                 }
212             }
213         }
214
215         if (velocity.x || velocity.y || velocity.z) {
216             for (unsigned j = 0; j < Person::players.size(); j++) {
217                 footvel = 0;
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.);
226
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];
234                             }
235                             Person::players[j]->num_weapons++;
236                             Person::players[j]->weaponids[0] = i;
237
238                             Person::players[j]->aitype = attacktypecutoff;
239                         } else {
240                             if (j != 0)
241                                 numthrowkill++;
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;
246                             else
247                                 Person::players[j]->weaponstuckwhere = 0;
248
249                             Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
250
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;
261                             Normalise(&footvel);
262                             if (bloodtoggle && tutoriallevel != 1)
263                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
264
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;
273                                 owner = j;
274                                 bloody = 2;
275                                 blooddrip = 5;
276                             }
277
278                             emit_sound_at(fleshstabsound, position, 128.);
279
280                             if (animation[Person::players[0]->animTarget].height == highheight)
281                                 award_bonus(0, ninja);
282                             else
283                                 award_bonus(0, Bullseyebonus);
284                         }
285                     } else {
286                         missed = 1;
287                     }
288                 }
289             }
290         }
291         if (position.y < terrain.getHeight(position.x, position.z)) {
292             if (terrain.getOpacity(position.x, position.z) < .2) {
293                 velocity = 0;
294                 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
295                     position = colpoint * terrain.scale;
296                 } else {
297                     position.y = terrain.getHeight(position.x, position.z);
298                 }
299
300                 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
301                 normalrot = terrain.getNormal(position.x, position.z) * -1;
302                 velocity = 0;
303                 glMatrixMode(GL_MODELVIEW);
304                 glPushMatrix();
305                 GLfloat M[16];
306                 glLoadIdentity();
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);
317                 tippoint.x = M[12];
318                 tippoint.y = M[13];
319                 tippoint.z = M[14];
320                 glPopMatrix();
321                 position -= tippoint * .15;
322                 XYZ temppoint1, temppoint2, tempforward;
323
324                 rotation3 = 0;
325                 smallrotation = 90;
326                 smallrotation2 = 0;
327                 bigtilt = 0;
328                 bigtilt2 = 0;
329                 bigrotation = 0;
330
331                 emit_sound_at(knifesheathesound, position, 128.);
332
333                 XYZ terrainlight;
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);
344                 }
345
346                 bloody = 0;
347             } else {
348                 physics = 1;
349                 firstfree = 1;
350                 position -= velocity * multiplier;
351                 tippoint -= velocity * multiplier;
352                 tipvelocity = velocity;
353             }
354         }
355         if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
356             velocity.y += gravity * multiplier;
357
358             XYZ temppoint1, temppoint2, tempforward;
359             float distance;
360
361             temppoint1 = 0;
362             temppoint2 = velocity;
363             distance = findDistance(&temppoint1, &temppoint2);
364             rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
365             rotation2 *= 360 / 6.28;
366             temppoint1.y = 0;
367             temppoint2.y = 0;
368             rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
369             rotation1 *= 360 / 6.28;
370             rotation3 = 0;
371             smallrotation = 90;
372             smallrotation2 = 0;
373             bigtilt = 0;
374             bigtilt2 = 0;
375             bigrotation = 0;
376             if (temppoint1.x > temppoint2.x)
377                 rotation1 = 360 - rotation1;
378         }
379
380     }
381
382     //Sword physics
383     XYZ mid;
384     XYZ oldmid;
385     XYZ oldmid2;
386
387     tempmult = multiplier;
388     multiplier /= 10;
389     for (int l = 0; l < 10; l++) {
390         if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
391             //move
392             position += velocity * multiplier;
393             tippoint += tipvelocity * multiplier;
394
395             //Length constrain
396             midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
397             vel = tippoint - midp;
398             Normalise(&vel);
399             newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
400             newpoint2 = midp + vel * length * (mass / (mass + tipmass));
401             if (!freeze) {
402                 if (freetime > .04) {
403                     velocity = velocity + (newpoint1 - position) / multiplier;
404                     tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
405                 }
406             }
407             position = newpoint1;
408             tippoint = newpoint2;
409
410
411             //Object collisions
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];
418
419                         if (firstfree) {
420                             if (type == staff) {
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) {
425                                     XYZ diff;
426                                     diff = (colpoint - position);
427                                     Normalise(&diff);
428                                     hitsomething = 1;
429
430                                     tippoint += (colpoint - position) + diff * .05;
431                                     position = colpoint + diff * .05;
432                                     oldtippoint = tippoint;
433                                     oldposition = tippoint;
434                                 }
435                             } else {
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) {
440                                     XYZ diff;
441                                     diff = (colpoint - tippoint);
442                                     Normalise(&diff);
443                                     hitsomething = 1;
444
445                                     position += (colpoint - tippoint) + diff * .05;
446                                     tippoint = colpoint + diff * .05;
447                                     oldposition = position;
448                                     oldtippoint = tippoint;
449                                 }
450                             }
451                         }
452
453                         start = oldposition;
454                         end = position;
455                         whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
456                         if (whichhit != -1) {
457                             hitsomething = 1;
458                             position = colpoint;
459                             terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
460                             ReflectVector(&velocity, &terrainnormal);
461                             position += terrainnormal * .002;
462
463                             bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
464                             if (findLengthfast(&velocity) < findLengthfast(&bounceness))
465                                 bounceness = 0;
466                             frictionness = abs(normaldotproduct(velocity, terrainnormal));
467                             velocity -= bounceness;
468                             if (1 - friction * frictionness > 0)
469                                 velocity *= 1 - friction * frictionness;
470                             else
471                                 velocity = 0;
472                             velocity += bounceness * elasticity;
473
474                             if (findLengthfast(&bounceness) > 1) {
475                                 int whichsound;
476                                 if (type == staff)
477                                     whichsound = footstepsound3 + abs(Random() % 2);
478                                 else
479                                     whichsound = clank1sound + abs(Random() % 4);
480                                 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
481                             }
482                         }
483                         start = oldtippoint;
484                         end = tippoint;
485                         whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
486                         if (whichhit != -1) {
487                             hitsomething = 1;
488                             tippoint = colpoint;
489                             terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
490                             ReflectVector(&tipvelocity, &terrainnormal);
491                             tippoint += terrainnormal * .002;
492
493                             bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
494                             if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
495                                 bounceness = 0;
496                             frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
497                             tipvelocity -= bounceness;
498                             if (1 - friction * frictionness > 0)
499                                 tipvelocity *= 1 - friction * frictionness;
500                             else
501                                 tipvelocity = 0;
502                             tipvelocity += bounceness * elasticity;
503
504                             if (findLengthfast(&bounceness) > 1) {
505                                 int whichsound;
506                                 if (type == staff)
507                                     whichsound = footstepsound3 + abs(Random() % 2);
508                                 else
509                                     whichsound = clank1sound + abs(Random() % 4);
510                                 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
511                             }
512                         }
513
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;
517                                 oldmid2 = mid;
518                                 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
519
520                                 start = oldmid;
521                                 end = mid;
522                                 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
523                                 if (whichhit != -1) {
524                                     hitsomething = 1;
525                                     mid = colpoint;
526                                     terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
527                                     ReflectVector(&velocity, &terrainnormal);
528
529                                     bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
530                                     if (findLengthfast(&velocity) < findLengthfast(&bounceness))
531                                         bounceness = 0;
532                                     frictionness = abs(normaldotproduct(velocity, terrainnormal));
533                                     velocity -= bounceness;
534                                     if (1 - friction * frictionness > 0)
535                                         velocity *= 1 - friction * frictionness;
536                                     else
537                                         velocity = 0;
538                                     velocity += bounceness * elasticity;
539
540                                     if (findLengthfast(&bounceness) > 1) {
541                                         int whichsound;
542                                         if (type == staff)
543                                             whichsound = footstepsound3 + abs(Random() % 2);
544                                         else
545                                             whichsound = clank1sound + abs(Random() % 4);
546                                         emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
547                                     }
548                                     position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
549                                 }
550
551                                 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
552                                 oldmid2 = mid;
553                                 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
554
555                                 start = oldmid;
556                                 end = mid;
557                                 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
558                                 if (whichhit != -1) {
559                                     hitsomething = 1;
560                                     mid = colpoint;
561                                     terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
562                                     ReflectVector(&tipvelocity, &terrainnormal);
563
564                                     bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
565                                     if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
566                                         bounceness = 0;
567                                     frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
568                                     tipvelocity -= bounceness;
569                                     if (1 - friction * frictionness > 0)
570                                         tipvelocity *= 1 - friction * frictionness;
571                                     else
572                                         tipvelocity = 0;
573                                     tipvelocity += bounceness * elasticity;
574
575                                     if (findLengthfast(&bounceness) > 1) {
576                                         int whichsound;
577                                         if (type == staff)
578                                             whichsound = footstepsound3 + abs(Random() % 2);
579                                         else
580                                             whichsound = clank1sound + abs(Random() % 4);
581                                         emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
582                                     }
583                                     tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
584                                 }
585                             }
586                         else {
587                             start = position;
588                             end = tippoint;
589                             whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
590                             if (whichhit != -1) {
591                                 hitsomething = 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;
601                                     }
602                                 }
603                                 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint )) {
604                                     if (distance < closestdistance || closestdistance == -1) {
605                                         closestpoint = colpoint;
606                                         closestdistance = distance;
607                                     }
608                                 }
609                                 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint )) {
610                                     if (distance < closestdistance || closestdistance == -1) {
611                                         closestpoint = colpoint;
612                                         closestdistance = distance;
613                                     }
614                                 }
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);
622                                     }
623                                 }
624                             }
625                         }
626                     }
627                 }
628             //Terrain collisions
629             whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
630             if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
631                 hitsomething = 1;
632                 if (whichhit != -1)
633                     position = colpoint * terrain.scale;
634                 else
635                     position.y = terrain.getHeight(position.x, position.z);
636
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))
642                     bounceness = 0;
643                 frictionness = abs(normaldotproduct(velocity, terrainnormal));
644                 velocity -= bounceness;
645                 if (1 - friction * frictionness > 0)
646                     velocity *= 1 - friction * frictionness;
647                 else
648                     velocity = 0;
649                 if (terrain.getOpacity(position.x, position.z) < .2)
650                     velocity += bounceness * elasticity * .3;
651                 else
652                     velocity += bounceness * elasticity;
653
654                 if (findLengthfast(&bounceness) > 1) {
655                     int whichsound;
656                     if (terrain.getOpacity(position.x, position.z) > .2) {
657                         if (type == staff)
658                             whichsound = footstepsound3 + abs(Random() % 2);
659                         else
660                             whichsound = clank1sound + abs(Random() % 4);
661                     } else {
662                         whichsound = footstepsound + abs(Random() % 2);
663                     }
664                     emit_sound_at(whichsound, position,
665                                   findLengthfast(&bounceness)
666                                   * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
667
668                     if (terrain.getOpacity(position.x, position.z) < .2) {
669                         XYZ terrainlight;
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);
680                         }
681                     }
682                 }
683             }
684             whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
685             if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
686                 if (whichhit != -1)
687                     tippoint = colpoint * terrain.scale;
688                 else
689                     tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
690
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))
696                     bounceness = 0;
697                 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
698                 tipvelocity -= bounceness;
699                 if (1 - friction * frictionness > 0)
700                     tipvelocity *= 1 - friction * frictionness;
701                 else
702                     tipvelocity = 0;
703                 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2)
704                     tipvelocity += bounceness * elasticity * .3;
705                 else
706                     tipvelocity += bounceness * elasticity;
707
708                 if (findLengthfast(&bounceness) > 1) {
709                     int whichsound;
710                     if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
711                         if (type == staff)
712                             whichsound = footstepsound3 + abs(Random() % 2);
713                         else
714                             whichsound = clank1sound + abs(Random() % 4);
715                     } else {
716                         whichsound = footstepsound + abs(Random() % 2);
717                     }
718                     emit_sound_at(whichsound, tippoint,
719                                   findLengthfast(&bounceness)
720                                   * (terrain.getOpacity(tippoint.x, tippoint.z) > .2  ? 128. : 32.));
721
722                     if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
723                         XYZ terrainlight;
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);
734                         }
735                     }
736                 }
737             }
738
739             //Edges
740             mid = position + tippoint;
741             mid /= 2;
742             mid += (position - mid) / 20;
743             oldmid = mid;
744             if (mid.y < terrain.getHeight(mid.x, mid.z)) {
745                 hitsomething = 1;
746                 mid.y = terrain.getHeight(mid.x, mid.z);
747
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))
753                     bounceness = 0;
754                 frictionness = abs(normaldotproduct(velocity, terrainnormal));
755                 velocity -= bounceness;
756                 if (1 - friction * frictionness > 0)
757                     velocity *= 1 - friction * frictionness;
758                 else
759                     velocity = 0;
760                 if (terrain.getOpacity(mid.x, mid.z) < .2)
761                     velocity += bounceness * elasticity * .3;
762                 else
763                     velocity += bounceness * elasticity;
764
765                 if (findLengthfast(&bounceness) > 1) {
766                     int whichsound;
767                     if (terrain.getOpacity(mid.x, mid.z) > .2) {
768                         if (type == staff)
769                             whichsound = footstepsound3 + abs(Random() % 2);
770                         if (type != staff)
771                             whichsound = clank1sound + abs(Random() % 4);
772                     } else {
773                         whichsound = footstepsound + abs(Random() % 2);
774                     }
775                     emit_sound_at(whichsound, mid,
776                                   findLengthfast(&bounceness)
777                                   * (terrain.getOpacity(position.x, position.z) > .2
778                                      ? 128.
779                                      : 32.));
780                 }
781                 position += (mid - oldmid) * 20;
782             }
783
784             mid = position + tippoint;
785             mid /= 2;
786             mid += (tippoint - mid) / 20;
787             oldmid = mid;
788             if (mid.y < terrain.getHeight(mid.x, mid.z)) {
789                 hitsomething = 1;
790                 mid.y = terrain.getHeight(mid.x, mid.z);
791
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))
797                     bounceness = 0;
798                 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
799                 tipvelocity -= bounceness;
800                 if (1 - friction * frictionness > 0)
801                     tipvelocity *= 1 - friction * frictionness;
802                 else
803                     tipvelocity = 0;
804                 if (terrain.getOpacity(mid.x, mid.z) < .2)
805                     tipvelocity += bounceness * elasticity * .3;
806                 else
807                     tipvelocity += bounceness * elasticity;
808
809                 if (findLengthfast(&bounceness) > 1) {
810                     int whichsound;
811                     if (terrain.getOpacity(mid.x, mid.z) > .2) {
812                         if (type == staff)
813                             whichsound = footstepsound3 + abs(Random() % 2);
814                         if (type != staff)
815                             whichsound = clank1sound + abs(Random() % 4);
816                     } else {
817                         whichsound = footstepsound + abs(Random() % 2);
818                     }
819                     emit_sound_at(whichsound, mid,
820                                   findLengthfast(&bounceness)
821                                   * (terrain.getOpacity(position.x, position.z) > .2
822                                      ? 128.
823                                      : 32.));
824                 }
825                 tippoint += (mid - oldmid) * 20;
826             }
827             //Gravity
828             velocity.y += gravity * multiplier;
829             tipvelocity.y += gravity * multiplier;
830
831             //Rotation
832             XYZ temppoint1, temppoint2, tempforward;
833             float distance;
834
835             temppoint1 = position;
836             temppoint2 = tippoint;
837             distance = findDistance(&temppoint1, &temppoint2);
838             rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
839             rotation2 *= 360 / 6.28;
840             temppoint1.y = 0;
841             temppoint2.y = 0;
842             rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
843             rotation1 *= 360 / 6.28;
844             rotation3 = 0;
845             smallrotation = 90;
846             smallrotation2 = 0;
847             bigtilt = 0;
848             bigtilt2 = 0;
849             bigrotation = 0;
850             if (temppoint1.x > temppoint2.x)
851                 rotation1 = 360 - rotation1;
852
853             //Stop moving
854             if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
855                 freetime += multiplier;
856             }
857
858             if (freetime > .4) {
859                 velocity = 0;
860                 tipvelocity = 0;
861             }
862             firstfree = 0;
863         }
864     }
865     multiplier = tempmult;
866     if (blooddrip && bloody) {
867         blooddripdelay -= blooddrip * multiplier / 2;
868         blooddrip -= multiplier;
869         if (blooddrip < 0)
870             blooddrip = 0;
871         if (blooddrip > 5)
872             blooddrip = 5;
873         if (blooddripdelay < 0 && bloodtoggle) {
874             blooddripdelay = 1;
875             XYZ bloodvel;
876             XYZ bloodloc;
877             bloodloc = position + (tippoint - position) * .7;
878             bloodloc.y -= .05;
879             if (bloodtoggle) {
880                 bloodvel = 0;
881                 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
882             }
883         }
884     }
885     if (onfire) {
886         flamedelay -= multiplier;
887         if (onfire && flamedelay <= 0) {
888             flamedelay = .020;
889             flamedelay -= multiplier;
890             normalrot = 0;
891             if (owner != -1) {
892                 normalrot = Person::players[owner]->velocity;
893             }
894             normalrot.y += 1;
895             if (owner != -1) {
896                 if (Person::players[owner]->onterrain) {
897                     normalrot.y = 1;
898                 }
899             }
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);
903         }
904     }
905
906     if (!onfire && owner == -1 && type != staff) {
907         flamedelay -= multiplier;
908         if (flamedelay <= 0) {
909             flamedelay = .020;
910             flamedelay -= multiplier;
911             normalrot = 0;
912             if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
913                 XYZ shinepoint;
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);
918             }
919         }
920     }
921 }
922
923 void Weapons::DoStuff()
924 {
925     //Move
926     int i = 0;
927     for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
928         weapon->DoStuff(i++);
929     }
930 }
931
932 void Weapon::Draw()
933 {
934     static XYZ terrainlight;
935     static GLfloat M[16];
936
937     if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
938             distsq(&viewer, &position) < viewdistance * viewdistance)) {
939         bool draw = false;
940         if (owner == -1) {
941             draw = true;
942             if (velocity.x && !physics)
943                 drawhowmany = 10;
944             else
945                 drawhowmany = 1;
946         } else {
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)
949                     draw = true;
950             if (
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
967             ) {
968                 drawhowmany = 10;
969             } else {
970                 drawhowmany = 1;
971             }
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;
981             }
982         }
983         if (draw) {
984             terrainlight = terrain.getLighting(position.x, position.z);
985             if (drawhowmany > 0) {
986                 glAlphaFunc(GL_GREATER, 0.01);
987             }
988             for (int j = drawhowmany; j > 0; j--) {
989                 glMatrixMode(GL_MODELVIEW);
990                 glPushMatrix();
991                 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
992                 if (owner == -1)
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));
994                 else
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);
1004
1005                 if (owner != -1) {
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);
1008                     }
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);
1011                     }
1012                 }
1013
1014                 glEnable(GL_LIGHTING);
1015                 switch (type) {
1016                 case knife:
1017                     if (!bloody || !bloodtoggle)
1018                         throwingknifemodel.drawdifftex(knifetextureptr);
1019                     if (bloodtoggle) {
1020                         if (bloody == 1)
1021                             throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1022                         if (bloody == 2)
1023                             throwingknifemodel.drawdifftex(bloodknifetextureptr);
1024                     }
1025                     break;
1026                 case sword:
1027                     if (!bloody || !bloodtoggle)
1028                         swordmodel.drawdifftex(swordtextureptr);
1029                     if (bloodtoggle) {
1030                         if (bloody == 1)
1031                             swordmodel.drawdifftex(lightbloodswordtextureptr);
1032                         if (bloody == 2)
1033                             swordmodel.drawdifftex(bloodswordtextureptr);
1034                     }
1035                     break;
1036                 case staff:
1037                     staffmodel.drawdifftex(stafftextureptr);
1038                     break;
1039                 }
1040
1041                 glPopMatrix();
1042             }
1043
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;
1054             if (owner != -1)
1055                 lastdrawnanim = Person::players[owner]->animCurrent;
1056         }
1057         if (owner != -1) {
1058             glMatrixMode(GL_MODELVIEW);
1059             glPushMatrix();
1060             glLoadIdentity();
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);
1072             tippoint.x = M[12];
1073             tippoint.y = M[13];
1074             tippoint.z = M[14];
1075             glPopMatrix();
1076         }
1077     }
1078 }
1079
1080 int Weapons::Draw()
1081 {
1082     glAlphaFunc(GL_GREATER, 0.9);
1083     glEnable(GL_TEXTURE_2D);
1084     glEnable(GL_BLEND);
1085     glEnable(GL_CULL_FACE);
1086     glCullFace(GL_FRONT);
1087     glDepthMask(1);
1088
1089     for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
1090         weapon->Draw();
1091     }
1092     return 0;
1093 }
1094
1095 Weapons::Weapons()
1096 {
1097 }
1098
1099 Weapons::~Weapons()
1100 {
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();
1108 }
1109