]> git.jsancho.org Git - lugaru.git/blob - Source/Objects/Weapons.cpp
Rename all C++ headers with .hpp extension
[lugaru.git] / Source / Objects / Weapons.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 This file is part of Lugaru.
8
9 Lugaru is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 Lugaru is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "Objects/Weapons.hpp"
24
25 #include "Animation/Animation.hpp"
26 #include "Audio/openal_wrapper.hpp"
27 #include "Audio/Sounds.hpp"
28 #include "Game.hpp"
29 #include "Level/Awards.hpp"
30
31 extern float multiplier;
32 extern Terrain terrain;
33 extern float gravity;
34 extern int environment;
35 extern int detail;
36 extern FRUSTUM frustum;
37 extern XYZ viewer;
38 extern float realmultiplier;
39 extern int slomo;
40 extern float slomodelay;
41 extern bool cellophane;
42 extern float texdetail;
43 extern GLubyte bloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
48 extern float woozy;
49 extern float viewdistance;
50 extern float blackout;
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 float tempmult;
120
121     if (owner != -1) {
122         oldowner = owner;
123     }
124     if (damage >= 2 && type == staff && owner != -1) { // the staff breaks
125         emit_sound_at(staffbreaksound, tippoint);
126         XYZ tempvel;
127         for (int j = 0; j < 40; j++) {
128             tempvel.x = float(abs(Random() % 100) - 50) / 20;
129             tempvel.y = float(abs(Random() % 100) - 50) / 20;
130             tempvel.z = float(abs(Random() % 100) - 50) / 20;
131             Sprite::MakeSprite(splintersprite, position + (tippoint - position) * ((float)j - 8) / 32, tempvel * .5, 115 / 255, 73 / 255, 12 / 255, .1, 1);
132         }
133         if (owner != -1) {
134             Person::players[owner]->weaponactive = -1;
135             Person::players[owner]->num_weapons--;
136             if (Person::players[owner]->num_weapons) {
137                 Person::players[owner]->weaponids[0] = Person::players[owner]->weaponids[Person::players[owner]->num_weapons];
138                 if (Person::players[owner]->weaponstuck == Person::players[owner]->num_weapons)
139                     Person::players[owner]->weaponstuck = 0;
140             }
141         }
142         owner = -1;
143         hitsomething = 0;
144         missed = 1;
145         freetime = 0;
146         firstfree = 1;
147         position = 0;
148         physics = 0;
149     }
150     oldposition = position;
151     oldtippoint = tippoint;
152     if (owner == -1 && (velocity.x || velocity.y || velocity.z) && !physics) { // if the weapon is flying
153         position += velocity * multiplier;
154         tippoint += velocity * multiplier;
155         whichpatchx = position.x / (terrain.size / subdivision * terrain.scale);
156         whichpatchz = position.z / (terrain.size / subdivision * terrain.scale);
157         if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
158             if (terrain.patchobjectnum[whichpatchx][whichpatchz]) { // if there are objects where the weapon is
159                 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) { // check for collision
160                     int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
161                     start = oldtippoint;
162                     end = tippoint;
163                     whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
164                     if (whichhit != -1) {
165                         if (objects.type[k] == treetrunktype) {
166                             objects.model[k].MakeDecal(breakdecal, DoRotation(colpoint - objects.position[k], 0, -objects.yaw[k], 0), .1, 1, Random() % 360);
167                             normalrot = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0);
168                             velocity = 0;
169                             if (type == knife)
170                                 position = colpoint - normalrot * .1;
171                             else if (type == sword)
172                                 position = colpoint - normalrot * .2;
173                             else if (type == staff)
174                                 position = colpoint - normalrot * .2;
175                             XYZ temppoint1, temppoint2;
176                             float distance;
177
178                             temppoint1 = 0;
179                             temppoint2 = normalrot;
180                             distance = findDistance(&temppoint1, &temppoint2);
181                             rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
182                             rotation2 *= 360 / 6.28;
183                             temppoint1.y = 0;
184                             temppoint2.y = 0;
185                             rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
186                             rotation1 *= 360 / 6.28;
187                             if (temppoint1.x > temppoint2.x)
188                                 rotation1 = 360 - rotation1;
189
190                             rotation3 = 0;
191                             smallrotation = 90;
192                             smallrotation2 = 0;
193                             bigtilt = 0;
194                             bigtilt2 = 0;
195                             bigrotation = 0;
196
197                             emit_sound_at(knifesheathesound, position, 128.);
198
199                             bloody = 0;
200
201                             Sprite::MakeSprite(cloudimpactsprite, position, velocity, 1, 1, 1, .8, .3);
202                         } else {
203                             physics = 1;
204                             firstfree = 1;
205                             position -= velocity * multiplier;
206                             tippoint -= velocity * multiplier;
207                             tipvelocity = velocity;
208                         }
209                     }
210                 }
211             }
212         }
213
214         if (velocity.x || velocity.y || velocity.z) {
215             for (unsigned j = 0; j < Person::players.size(); j++) {
216                 footvel = 0;
217                 footpoint = DoRotation((Person::players[j]->jointPos(abdomen) + Person::players[j]->jointPos(neck)) / 2, 0, Person::players[j]->yaw, 0) * Person::players[j]->scale + Person::players[j]->coords;
218                 if (owner == -1 && distsqflat(&position, &Person::players[j]->coords) < 1.5 &&
219                         distsq(&position, &Person::players[j]->coords) < 4 && Person::players[j]->weaponstuck == -1 &&
220                         !Person::players[j]->skeleton.free && (int(j) != oldowner)) {
221                     if ((Person::players[j]->aitype != attacktypecutoff || abs(Random() % 6) == 0 || (Person::players[j]->animTarget != backhandspringanim && Person::players[j]->animTarget != rollanim && Person::players[j]->animTarget != flipanim && Random() % 2 == 0)) && !missed) {
222                         if ( (Person::players[j]->creature == wolftype && Random() % 3 != 0 && Person::players[j]->weaponactive == -1 && (Person::players[j]->isIdle() || Person::players[j]->isRun() || Person::players[j]->animTarget == walkanim)) ||
223                                 (Person::players[j]->creature == rabbittype && Random() % 2 == 0 && Person::players[j]->aitype == attacktypecutoff && Person::players[j]->weaponactive == -1)) {
224                             emit_sound_at(knifedrawsound, Person::players[j]->coords, 128.);
225
226                             Person::players[j]->animTarget = removeknifeanim;
227                             Person::players[j]->frameTarget = 1;
228                             Person::players[j]->target = 1;
229                             Person::players[j]->takeWeapon(i);
230
231                             Person::players[j]->aitype = attacktypecutoff;
232                         } else {
233                             if (j != 0)
234                                 numthrowkill++;
235                             Person::players[j]->num_weapons++;
236                             Person::players[j]->weaponstuck = Person::players[j]->num_weapons - 1;
237                             if (normaldotproduct(Person::players[j]->facing, velocity) > 0)
238                                 Person::players[j]->weaponstuckwhere = 1;
239                             else
240                                 Person::players[j]->weaponstuckwhere = 0;
241
242                             Person::players[j]->weaponids[Person::players[j]->num_weapons - 1] = i;
243
244                             Person::players[j]->RagDoll(0);
245                             Person::players[j]->jointVel(abdomen) += velocity * 2;
246                             Person::players[j]->jointVel(neck) += velocity * 2;
247                             Person::players[j]->jointVel(rightshoulder) += velocity * 2;
248                             Person::players[j]->jointVel(leftshoulder) += velocity * 2;
249                             if (bloodtoggle && tutoriallevel != 1)
250                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
251                             if (tutoriallevel == 1)
252                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
253                             footvel = tippoint - position;
254                             Normalise(&footvel);
255                             if (bloodtoggle && tutoriallevel != 1)
256                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
257
258                             if (tutoriallevel != 1) {
259                                 if (Person::players[j]->weaponstuckwhere == 0)
260                                     Person::players[j]->DoBloodBig(2, 205);
261                                 if (Person::players[j]->weaponstuckwhere == 1)
262                                     Person::players[j]->DoBloodBig(2, 200);
263                                 Person::players[j]->damage += 200 / Person::players[j]->armorhigh;
264                                 Person::players[j]->deathbleeding = 1;
265                                 Person::players[j]->bloodloss += (200 + abs((float)(Random() % 40)) - 20) / Person::players[j]->armorhigh;
266                                 owner = j;
267                                 bloody = 2;
268                                 blooddrip = 5;
269                             }
270
271                             emit_sound_at(fleshstabsound, position, 128.);
272
273                             if (Animation::animations[Person::players[0]->animTarget].height == highheight)
274                                 award_bonus(0, ninja);
275                             else
276                                 award_bonus(0, Bullseyebonus);
277                         }
278                     } else {
279                         missed = 1;
280                     }
281                 }
282             }
283         }
284         if (position.y < terrain.getHeight(position.x, position.z)) {
285             if (terrain.getOpacity(position.x, position.z) < .2) {
286                 velocity = 0;
287                 if (terrain.lineTerrain(oldposition, position, &colpoint) != -1) {
288                     position = colpoint * terrain.scale;
289                 } else {
290                     position.y = terrain.getHeight(position.x, position.z);
291                 }
292
293                 terrain.MakeDecal(shadowdecalpermanent, position, .06, .5, 0);
294                 normalrot = terrain.getNormal(position.x, position.z) * -1;
295                 velocity = 0;
296                 glMatrixMode(GL_MODELVIEW);
297                 glPushMatrix();
298                 GLfloat M[16];
299                 glLoadIdentity();
300                 glRotatef(bigrotation, 0, 1, 0);
301                 glRotatef(bigtilt2, 1, 0, 0);
302                 glRotatef(bigtilt, 0, 0, 1);
303                 glRotatef(-rotation1 + 90, 0, 1, 0);
304                 glRotatef(-rotation2 + 90, 0, 0, 1);
305                 glRotatef(-rotation3, 0, 1, 0);
306                 glRotatef(smallrotation, 1, 0, 0);
307                 glRotatef(smallrotation2, 0, 1, 0);
308                 glTranslatef(0, 0, 1);
309                 glGetFloatv(GL_MODELVIEW_MATRIX, M);
310                 tippoint.x = M[12];
311                 tippoint.y = M[13];
312                 tippoint.z = M[14];
313                 glPopMatrix();
314                 position -= tippoint * .15;
315                 XYZ temppoint1, temppoint2;
316
317                 rotation3 = 0;
318                 smallrotation = 90;
319                 smallrotation2 = 0;
320                 bigtilt = 0;
321                 bigtilt2 = 0;
322                 bigrotation = 0;
323
324                 emit_sound_at(knifesheathesound, position, 128.);
325
326                 XYZ terrainlight;
327                 terrainlight = terrain.getLighting(position.x, position.z);
328                 if (environment == snowyenvironment) {
329                     if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
330                         Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
331                 } else if (environment == grassyenvironment) {
332                     if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
333                         Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
334                 } else if (environment == desertenvironment) {
335                     if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
336                         Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
337                 }
338
339                 bloody = 0;
340             } else {
341                 physics = 1;
342                 firstfree = 1;
343                 position -= velocity * multiplier;
344                 tippoint -= velocity * multiplier;
345                 tipvelocity = velocity;
346             }
347         }
348         if (velocity.x != 0 || velocity.z != 0 || velocity.y != 0) {
349             velocity.y += gravity * multiplier;
350
351             XYZ temppoint1, temppoint2;
352             float distance;
353
354             temppoint1 = 0;
355             temppoint2 = velocity;
356             distance = findDistance(&temppoint1, &temppoint2);
357             rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
358             rotation2 *= 360 / 6.28;
359             temppoint1.y = 0;
360             temppoint2.y = 0;
361             rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
362             rotation1 *= 360 / 6.28;
363             rotation3 = 0;
364             smallrotation = 90;
365             smallrotation2 = 0;
366             bigtilt = 0;
367             bigtilt2 = 0;
368             bigrotation = 0;
369             if (temppoint1.x > temppoint2.x)
370                 rotation1 = 360 - rotation1;
371         }
372
373     }
374
375     //Sword physics
376     XYZ mid;
377     XYZ oldmid;
378     XYZ oldmid2;
379
380     tempmult = multiplier;
381     multiplier /= 10;
382     for (int l = 0; l < 10; l++) {
383         if (owner == -1 && (velocity.x || velocity.y || velocity.z) && physics) {
384             //move
385             position += velocity * multiplier;
386             tippoint += tipvelocity * multiplier;
387
388             //Length constrain
389             midp = (position * mass + tippoint * tipmass) / (mass + tipmass);
390             vel = tippoint - midp;
391             Normalise(&vel);
392             newpoint1 = midp - vel * length * (tipmass / (mass + tipmass));
393             newpoint2 = midp + vel * length * (mass / (mass + tipmass));
394             if (!freeze) {
395                 if (freetime > .04) {
396                     velocity = velocity + (newpoint1 - position) / multiplier;
397                     tipvelocity = tipvelocity + (newpoint2 - tippoint) / multiplier;
398                 }
399             }
400             position = newpoint1;
401             tippoint = newpoint2;
402
403
404             //Object collisions
405             whichpatchx = (position.x) / (terrain.size / subdivision * terrain.scale);
406             whichpatchz = (position.z) / (terrain.size / subdivision * terrain.scale);
407             if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision)
408                 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) {
409                     for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
410                         int k = terrain.patchobjects[whichpatchx][whichpatchz][j];
411
412                         if (firstfree) {
413                             if (type == staff) {
414                                 start = tippoint - (position - tippoint) / 5;
415                                 end = position + (position - tippoint) / 30;
416                                 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
417                                 if (whichhit != -1) {
418                                     XYZ diff;
419                                     diff = (colpoint - position);
420                                     Normalise(&diff);
421                                     hitsomething = 1;
422
423                                     tippoint += (colpoint - position) + diff * .05;
424                                     position = colpoint + diff * .05;
425                                     oldtippoint = tippoint;
426                                     oldposition = tippoint;
427                                 }
428                             } else {
429                                 start = position - (tippoint - position) / 5;
430                                 end = tippoint + (tippoint - position) / 30;
431                                 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
432                                 if (whichhit != -1) {
433                                     XYZ diff;
434                                     diff = (colpoint - tippoint);
435                                     Normalise(&diff);
436                                     hitsomething = 1;
437
438                                     position += (colpoint - tippoint) + diff * .05;
439                                     tippoint = colpoint + diff * .05;
440                                     oldposition = position;
441                                     oldtippoint = tippoint;
442                                 }
443                             }
444                         }
445
446                         start = oldposition;
447                         end = position;
448                         whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
449                         if (whichhit != -1) {
450                             hitsomething = 1;
451                             position = colpoint;
452                             terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
453                             ReflectVector(&velocity, &terrainnormal);
454                             position += terrainnormal * .002;
455
456                             bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
457                             if (findLengthfast(&velocity) < findLengthfast(&bounceness))
458                                 bounceness = 0;
459                             frictionness = abs(normaldotproduct(velocity, terrainnormal));
460                             velocity -= bounceness;
461                             if (1 - friction * frictionness > 0)
462                                 velocity *= 1 - friction * frictionness;
463                             else
464                                 velocity = 0;
465                             velocity += bounceness * elasticity;
466
467                             if (findLengthfast(&bounceness) > 1) {
468                                 int whichsound;
469                                 if (type == staff)
470                                     whichsound = footstepsound3 + abs(Random() % 2);
471                                 else
472                                     whichsound = clank1sound + abs(Random() % 4);
473                                 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
474                             }
475                         }
476                         start = oldtippoint;
477                         end = tippoint;
478                         whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
479                         if (whichhit != -1) {
480                             hitsomething = 1;
481                             tippoint = colpoint;
482                             terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
483                             ReflectVector(&tipvelocity, &terrainnormal);
484                             tippoint += terrainnormal * .002;
485
486                             bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
487                             if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
488                                 bounceness = 0;
489                             frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
490                             tipvelocity -= bounceness;
491                             if (1 - friction * frictionness > 0)
492                                 tipvelocity *= 1 - friction * frictionness;
493                             else
494                                 tipvelocity = 0;
495                             tipvelocity += bounceness * elasticity;
496
497                             if (findLengthfast(&bounceness) > 1) {
498                                 int whichsound;
499                                 if (type == staff)
500                                     whichsound = footstepsound3 + abs(Random() % 2);
501                                 else
502                                     whichsound = clank1sound + abs(Random() % 4);
503                                 emit_sound_at(whichsound, position, 128 * findLengthfast(&bounceness));
504                             }
505                         }
506
507                         if ((objects.type[k] != boxtype && objects.type[k] != platformtype && objects.type[k] != walltype && objects.type[k] != weirdtype) || objects.pitch[k] != 0)
508                             for (int m = 0; m < 2; m++) {
509                                 mid = (position * (21 + (float)m * 10) + tippoint * (19 - (float)m * 10)) / 40;
510                                 oldmid2 = mid;
511                                 oldmid = (oldposition * (21 + (float)m * 10) + oldtippoint * (19 - (float)m * 10)) / 40;
512
513                                 start = oldmid;
514                                 end = mid;
515                                 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
516                                 if (whichhit != -1) {
517                                     hitsomething = 1;
518                                     mid = colpoint;
519                                     terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
520                                     ReflectVector(&velocity, &terrainnormal);
521
522                                     bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
523                                     if (findLengthfast(&velocity) < findLengthfast(&bounceness))
524                                         bounceness = 0;
525                                     frictionness = abs(normaldotproduct(velocity, terrainnormal));
526                                     velocity -= bounceness;
527                                     if (1 - friction * frictionness > 0)
528                                         velocity *= 1 - friction * frictionness;
529                                     else
530                                         velocity = 0;
531                                     velocity += bounceness * elasticity;
532
533                                     if (findLengthfast(&bounceness) > 1) {
534                                         int whichsound;
535                                         if (type == staff)
536                                             whichsound = footstepsound3 + abs(Random() % 2);
537                                         else
538                                             whichsound = clank1sound + abs(Random() % 4);
539                                         emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
540                                     }
541                                     position += (mid - oldmid2) * (20 / (1 + (float)m * 10));
542                                 }
543
544                                 mid = (position * (19 - (float)m * 10) + tippoint * (21 + (float)m * 10)) / 40;
545                                 oldmid2 = mid;
546                                 oldmid = (oldposition * (19 - (float)m * 10) + oldtippoint * (21 + (float)m * 10)) / 40;
547
548                                 start = oldmid;
549                                 end = mid;
550                                 whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
551                                 if (whichhit != -1) {
552                                     hitsomething = 1;
553                                     mid = colpoint;
554                                     terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
555                                     ReflectVector(&tipvelocity, &terrainnormal);
556
557                                     bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
558                                     if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
559                                         bounceness = 0;
560                                     frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
561                                     tipvelocity -= bounceness;
562                                     if (1 - friction * frictionness > 0)
563                                         tipvelocity *= 1 - friction * frictionness;
564                                     else
565                                         tipvelocity = 0;
566                                     tipvelocity += bounceness * elasticity;
567
568                                     if (findLengthfast(&bounceness) > 1) {
569                                         int whichsound;
570                                         if (type == staff)
571                                             whichsound = footstepsound3 + abs(Random() % 2);
572                                         else
573                                             whichsound = clank1sound + abs(Random() % 4);
574                                         emit_sound_at(whichsound, mid, 128 * findLengthfast(&bounceness));
575                                     }
576                                     tippoint += (mid - oldmid2) * (20 / (1 + (float)m * 10));
577                                 }
578                             }
579                         else {
580                             start = position;
581                             end = tippoint;
582                             whichhit = objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]);
583                             if (whichhit != -1) {
584                                 hitsomething = 1;
585                                 closestdistance = -1;
586                                 closestswordpoint = colpoint; //(position+tippoint)/2;
587                                 point[0] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[0]], 0, objects.yaw[k], 0) + objects.position[k];
588                                 point[1] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[1]], 0, objects.yaw[k], 0) + objects.position[k];
589                                 point[2] = DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[2]], 0, objects.yaw[k], 0) + objects.position[k];
590                                 if (DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance, &colpoint )) {
591                                     if (distance < closestdistance || closestdistance == -1) {
592                                         closestpoint = colpoint;
593                                         closestdistance = distance;
594                                     }
595                                 }
596                                 if (DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance, &colpoint )) {
597                                     if (distance < closestdistance || closestdistance == -1) {
598                                         closestpoint = colpoint;
599                                         closestdistance = distance;
600                                     }
601                                 }
602                                 if (DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance, &colpoint )) {
603                                     if (distance < closestdistance || closestdistance == -1) {
604                                         closestpoint = colpoint;
605                                         closestdistance = distance;
606                                     }
607                                 }
608                                 if (closestdistance != -1 && isnormal(closestdistance)) {
609                                     if (DistancePointLine(&closestpoint, &position, &tippoint, &distance, &colpoint )) {
610                                         closestswordpoint = colpoint;
611                                         velocity += (closestpoint - closestswordpoint);
612                                         tipvelocity += (closestpoint - closestswordpoint);
613                                         position += (closestpoint - closestswordpoint);
614                                         tippoint += (closestpoint - closestswordpoint);
615                                     }
616                                 }
617                             }
618                         }
619                     }
620                 }
621             //Terrain collisions
622             whichhit = terrain.lineTerrain(oldposition, position, &colpoint);
623             if (whichhit != -1 || position.y < terrain.getHeight(position.x, position.z)) {
624                 hitsomething = 1;
625                 if (whichhit != -1)
626                     position = colpoint * terrain.scale;
627                 else
628                     position.y = terrain.getHeight(position.x, position.z);
629
630                 terrainnormal = terrain.getNormal(position.x, position.z);
631                 ReflectVector(&velocity, &terrainnormal);
632                 position += terrainnormal * .002;
633                 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
634                 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
635                     bounceness = 0;
636                 frictionness = abs(normaldotproduct(velocity, terrainnormal));
637                 velocity -= bounceness;
638                 if (1 - friction * frictionness > 0)
639                     velocity *= 1 - friction * frictionness;
640                 else
641                     velocity = 0;
642                 if (terrain.getOpacity(position.x, position.z) < .2)
643                     velocity += bounceness * elasticity * .3;
644                 else
645                     velocity += bounceness * elasticity;
646
647                 if (findLengthfast(&bounceness) > 1) {
648                     int whichsound;
649                     if (terrain.getOpacity(position.x, position.z) > .2) {
650                         if (type == staff)
651                             whichsound = footstepsound3 + abs(Random() % 2);
652                         else
653                             whichsound = clank1sound + abs(Random() % 4);
654                     } else {
655                         whichsound = footstepsound + abs(Random() % 2);
656                     }
657                     emit_sound_at(whichsound, position,
658                                   findLengthfast(&bounceness)
659                                   * (terrain.getOpacity(position.x, position.z) > .2 ? 128. : 32.));
660
661                     if (terrain.getOpacity(position.x, position.z) < .2) {
662                         XYZ terrainlight;
663                         terrainlight = terrain.getLighting(position.x, position.z);
664                         if (environment == snowyenvironment) {
665                             if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
666                                 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
667                         } else if (environment == grassyenvironment) {
668                             if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
669                                 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
670                         } else if (environment == desertenvironment) {
671                             if (distsq(&position, &viewer) < viewdistance * viewdistance / 4)
672                                 Sprite::MakeSprite(cloudsprite, position, velocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
673                         }
674                     }
675                 }
676             }
677             whichhit = terrain.lineTerrain(oldtippoint, tippoint, &colpoint);
678             if (whichhit != -1 || tippoint.y < terrain.getHeight(tippoint.x, tippoint.z)) {
679                 if (whichhit != -1)
680                     tippoint = colpoint * terrain.scale;
681                 else
682                     tippoint.y = terrain.getHeight(tippoint.x, tippoint.z);
683
684                 terrainnormal = terrain.getNormal(tippoint.x, tippoint.z);
685                 ReflectVector(&tipvelocity, &terrainnormal);
686                 tippoint += terrainnormal * .002;
687                 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
688                 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
689                     bounceness = 0;
690                 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
691                 tipvelocity -= bounceness;
692                 if (1 - friction * frictionness > 0)
693                     tipvelocity *= 1 - friction * frictionness;
694                 else
695                     tipvelocity = 0;
696                 if (terrain.getOpacity(tippoint.x, tippoint.z) < .2)
697                     tipvelocity += bounceness * elasticity * .3;
698                 else
699                     tipvelocity += bounceness * elasticity;
700
701                 if (findLengthfast(&bounceness) > 1) {
702                     int whichsound;
703                     if (terrain.getOpacity(tippoint.x, tippoint.z) > .2) {
704                         if (type == staff)
705                             whichsound = footstepsound3 + abs(Random() % 2);
706                         else
707                             whichsound = clank1sound + abs(Random() % 4);
708                     } else {
709                         whichsound = footstepsound + abs(Random() % 2);
710                     }
711                     emit_sound_at(whichsound, tippoint,
712                                   findLengthfast(&bounceness)
713                                   * (terrain.getOpacity(tippoint.x, tippoint.z) > .2  ? 128. : 32.));
714
715                     if (terrain.getOpacity(tippoint.x, tippoint.z) < .2) {
716                         XYZ terrainlight;
717                         terrainlight = terrain.getLighting(tippoint.x, tippoint.z);
718                         if (environment == snowyenvironment) {
719                             if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
720                                 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
721                         } else if (environment == grassyenvironment) {
722                             if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
723                                 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
724                         } else if (environment == desertenvironment) {
725                             if (distsq(&tippoint, &viewer) < viewdistance * viewdistance / 4)
726                                 Sprite::MakeSprite(cloudsprite, tippoint, tipvelocity, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
727                         }
728                     }
729                 }
730             }
731
732             //Edges
733             mid = position + tippoint;
734             mid /= 2;
735             mid += (position - mid) / 20;
736             oldmid = mid;
737             if (mid.y < terrain.getHeight(mid.x, mid.z)) {
738                 hitsomething = 1;
739                 mid.y = terrain.getHeight(mid.x, mid.z);
740
741                 terrainnormal = terrain.getNormal(mid.x, mid.z);
742                 ReflectVector(&velocity, &terrainnormal);
743                 //mid+=terrainnormal*.002;
744                 bounceness = terrainnormal * findLength(&velocity) * (abs(normaldotproduct(velocity, terrainnormal)));
745                 if (findLengthfast(&velocity) < findLengthfast(&bounceness))
746                     bounceness = 0;
747                 frictionness = abs(normaldotproduct(velocity, terrainnormal));
748                 velocity -= bounceness;
749                 if (1 - friction * frictionness > 0)
750                     velocity *= 1 - friction * frictionness;
751                 else
752                     velocity = 0;
753                 if (terrain.getOpacity(mid.x, mid.z) < .2)
754                     velocity += bounceness * elasticity * .3;
755                 else
756                     velocity += bounceness * elasticity;
757
758                 if (findLengthfast(&bounceness) > 1) {
759                     int whichsound;
760                     if (terrain.getOpacity(mid.x, mid.z) > .2) {
761                         if (type == staff)
762                             whichsound = footstepsound3 + abs(Random() % 2);
763                         if (type != staff)
764                             whichsound = clank1sound + abs(Random() % 4);
765                     } else {
766                         whichsound = footstepsound + abs(Random() % 2);
767                     }
768                     emit_sound_at(whichsound, mid,
769                                   findLengthfast(&bounceness)
770                                   * (terrain.getOpacity(position.x, position.z) > .2
771                                      ? 128.
772                                      : 32.));
773                 }
774                 position += (mid - oldmid) * 20;
775             }
776
777             mid = position + tippoint;
778             mid /= 2;
779             mid += (tippoint - mid) / 20;
780             oldmid = mid;
781             if (mid.y < terrain.getHeight(mid.x, mid.z)) {
782                 hitsomething = 1;
783                 mid.y = terrain.getHeight(mid.x, mid.z);
784
785                 terrainnormal = terrain.getNormal(mid.x, mid.z);
786                 ReflectVector(&tipvelocity, &terrainnormal);
787                 //mid+=terrainnormal*.002;
788                 bounceness = terrainnormal * findLength(&tipvelocity) * (abs(normaldotproduct(tipvelocity, terrainnormal)));
789                 if (findLengthfast(&tipvelocity) < findLengthfast(&bounceness))
790                     bounceness = 0;
791                 frictionness = abs(normaldotproduct(tipvelocity, terrainnormal));
792                 tipvelocity -= bounceness;
793                 if (1 - friction * frictionness > 0)
794                     tipvelocity *= 1 - friction * frictionness;
795                 else
796                     tipvelocity = 0;
797                 if (terrain.getOpacity(mid.x, mid.z) < .2)
798                     tipvelocity += bounceness * elasticity * .3;
799                 else
800                     tipvelocity += bounceness * elasticity;
801
802                 if (findLengthfast(&bounceness) > 1) {
803                     int whichsound;
804                     if (terrain.getOpacity(mid.x, mid.z) > .2) {
805                         if (type == staff)
806                             whichsound = footstepsound3 + abs(Random() % 2);
807                         if (type != staff)
808                             whichsound = clank1sound + abs(Random() % 4);
809                     } else {
810                         whichsound = footstepsound + abs(Random() % 2);
811                     }
812                     emit_sound_at(whichsound, mid,
813                                   findLengthfast(&bounceness)
814                                   * (terrain.getOpacity(position.x, position.z) > .2
815                                      ? 128.
816                                      : 32.));
817                 }
818                 tippoint += (mid - oldmid) * 20;
819             }
820             //Gravity
821             velocity.y += gravity * multiplier;
822             tipvelocity.y += gravity * multiplier;
823
824             //Rotation
825             XYZ temppoint1, temppoint2;
826             float distance;
827
828             temppoint1 = position;
829             temppoint2 = tippoint;
830             distance = findDistance(&temppoint1, &temppoint2);
831             rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
832             rotation2 *= 360 / 6.28;
833             temppoint1.y = 0;
834             temppoint2.y = 0;
835             rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
836             rotation1 *= 360 / 6.28;
837             rotation3 = 0;
838             smallrotation = 90;
839             smallrotation2 = 0;
840             bigtilt = 0;
841             bigtilt2 = 0;
842             bigrotation = 0;
843             if (temppoint1.x > temppoint2.x)
844                 rotation1 = 360 - rotation1;
845
846             //Stop moving
847             if (findLengthfast(&velocity) < .3 && findLengthfast(&tipvelocity) < .3 && hitsomething) {
848                 freetime += multiplier;
849             }
850
851             if (freetime > .4) {
852                 velocity = 0;
853                 tipvelocity = 0;
854             }
855             firstfree = 0;
856         }
857     }
858     multiplier = tempmult;
859     if (blooddrip && bloody) {
860         blooddripdelay -= blooddrip * multiplier / 2;
861         blooddrip -= multiplier;
862         if (blooddrip < 0)
863             blooddrip = 0;
864         if (blooddrip > 5)
865             blooddrip = 5;
866         if (blooddripdelay < 0 && bloodtoggle) {
867             blooddripdelay = 1;
868             XYZ bloodvel;
869             XYZ bloodloc;
870             bloodloc = position + (tippoint - position) * .7;
871             bloodloc.y -= .05;
872             if (bloodtoggle) {
873                 bloodvel = 0;
874                 Sprite::MakeSprite(bloodsprite, bloodloc, bloodvel, 1, 1, 1, .03, 1);
875             }
876         }
877     }
878     if (onfire) {
879         flamedelay -= multiplier;
880         if (onfire && flamedelay <= 0) {
881             flamedelay = .020;
882             flamedelay -= multiplier;
883             normalrot = 0;
884             if (owner != -1) {
885                 normalrot = Person::players[owner]->velocity;
886             }
887             normalrot.y += 1;
888             if (owner != -1) {
889                 if (Person::players[owner]->onterrain) {
890                     normalrot.y = 1;
891                 }
892             }
893             Sprite::MakeSprite(weaponflamesprite, position + tippoint * (((float)abs(Random() % 100)) / 600 + .05), normalrot, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3, 1);
894             Sprite::setLastSpriteSpeed(4);
895             Sprite::setLastSpriteAlivetime(.3);
896         }
897     }
898
899     if (!onfire && owner == -1 && type != staff) {
900         flamedelay -= multiplier;
901         if (flamedelay <= 0) {
902             flamedelay = .020;
903             flamedelay -= multiplier;
904             normalrot = 0;
905             if (Random() % 50 == 0 && distsq(&position, &viewer) > 80) {
906                 XYZ shinepoint;
907                 shinepoint = position + (tippoint - position) * (((float)abs(Random() % 100)) / 100);
908                 Sprite::MakeSprite(weaponshinesprite, shinepoint, normalrot, 1, 1, 1, (.1 + (float)abs(Random() % 100) / 200 - .25) * 1 / 3 * fast_sqrt(findDistance(&shinepoint, &viewer)), 1);
909                 Sprite::setLastSpriteSpeed(4);
910                 Sprite::setLastSpriteAlivetime(.3);
911             }
912         }
913     }
914 }
915
916 void Weapons::DoStuff()
917 {
918     //Move
919     int i = 0;
920     for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
921         weapon->DoStuff(i++);
922     }
923 }
924
925 void Weapon::Draw()
926 {
927     static XYZ terrainlight;
928     static GLfloat M[16];
929
930     if ((frustum.SphereInFrustum(position.x, position.y, position.z, 1) &&
931             distsq(&viewer, &position) < viewdistance * viewdistance)) {
932         bool draw = false;
933         if (owner == -1) {
934             draw = true;
935             if (velocity.x && !physics)
936                 drawhowmany = 10;
937             else
938                 drawhowmany = 1;
939         } else {
940             if (Person::players[owner]->occluded < 25)
941                 if ((frustum.SphereInFrustum(Person::players[owner]->coords.x, Person::players[owner]->coords.y + Person::players[owner]->scale * 3, Person::players[owner]->coords.z, Person::players[owner]->scale * 8) && distsq(&viewer, &Person::players[owner]->coords) < viewdistance * viewdistance) || Person::players[owner]->skeleton.free == 3)
942                     draw = true;
943             if (
944                 (Person::players[owner]->animTarget == knifeslashstartanim ||
945                  Person::players[owner]->animTarget == swordsneakattackanim ||
946                  (Person::players[owner]->animCurrent == staffhitanim && Person::players[owner]->frameCurrent > 1) ||
947                  (Person::players[owner]->animCurrent == staffhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
948                  (Person::players[owner]->animCurrent == staffspinhitanim && Person::players[owner]->frameCurrent > 1) ||
949                  (Person::players[owner]->animCurrent == staffspinhitreversedanim && Person::players[owner]->frameCurrent > 1) ||
950                  (Person::players[owner]->animCurrent == staffgroundsmashanim && Person::players[owner]->frameCurrent > 1) ||
951                  (Person::players[owner]->animTarget == swordslashanim && Person::players[owner]->frameTarget < 7) ||
952                  Person::players[owner]->animTarget == crouchstabanim ||
953                  Person::players[owner]->animTarget == swordslashreversalanim ||
954                  Person::players[owner]->animTarget == swordslashreversedanim ||
955                  Person::players[owner]->animTarget == knifefollowanim ||
956                  Person::players[owner]->animTarget == swordgroundstabanim ||
957                  Person::players[owner]->animTarget == knifethrowanim) &&
958                 Person::players[owner]->animTarget == lastdrawnanim &&
959                 !Person::players[owner]->skeleton.free
960             ) {
961                 drawhowmany = 10;
962             } else {
963                 drawhowmany = 1;
964             }
965             if (Person::players[owner]->animTarget == swordgroundstabanim) {
966                 lastdrawnrotation1 = rotation1;
967                 lastdrawnrotation2 = rotation2;
968                 lastdrawnrotation3 = rotation3;
969                 lastdrawnbigrotation = bigrotation;
970                 lastdrawnbigtilt = bigtilt;
971                 lastdrawnbigtilt2 = bigtilt2;
972                 lastdrawnsmallrotation = smallrotation;
973                 lastdrawnsmallrotation2 = smallrotation2;
974             }
975         }
976         if (draw) {
977             terrainlight = terrain.getLighting(position.x, position.z);
978             if (drawhowmany > 0) {
979                 glAlphaFunc(GL_GREATER, 0.01);
980             }
981             for (int j = drawhowmany; j > 0; j--) {
982                 glMatrixMode(GL_MODELVIEW);
983                 glPushMatrix();
984                 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, j / drawhowmany);
985                 if (owner == -1)
986                     glTranslatef(position.x * (((float)(j)) / drawhowmany) + lastdrawnposition.x * (1 - ((float)(j)) / drawhowmany), position.y * (((float)(j)) / drawhowmany) + lastdrawnposition.y * (1 - ((float)(j)) / drawhowmany), position.z * (((float)(j)) / drawhowmany) + lastdrawnposition.z * (1 - ((float)(j)) / drawhowmany));
987                 else
988                     glTranslatef(position.x * (((float)(j)) / drawhowmany) + lastdrawnposition.x * (1 - ((float)(j)) / drawhowmany), position.y * (((float)(j)) / drawhowmany) - .02 + lastdrawnposition.y * (1 - ((float)(j)) / drawhowmany), position.z * (((float)(j)) / drawhowmany) + lastdrawnposition.z * (1 - ((float)(j)) / drawhowmany));
989                 glRotatef(bigrotation * (((float)(j)) / drawhowmany) + lastdrawnbigrotation * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
990                 glRotatef(bigtilt2 * (((float)(j)) / drawhowmany) + lastdrawnbigtilt2 * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
991                 glRotatef(bigtilt * (((float)(j)) / drawhowmany) + lastdrawnbigtilt * (1 - ((float)(j)) / drawhowmany), 0, 0, 1);
992                 glRotatef(-rotation1 * (((float)(j)) / drawhowmany) - lastdrawnrotation1 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 1, 0);
993                 glRotatef(-rotation2 * (((float)(j)) / drawhowmany) - lastdrawnrotation2 * (1 - ((float)(j)) / drawhowmany) + 90, 0, 0, 1);
994                 glRotatef(-rotation3 * (((float)(j)) / drawhowmany) - lastdrawnrotation3 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
995                 glRotatef(smallrotation * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation * (1 - ((float)(j)) / drawhowmany), 1, 0, 0);
996                 glRotatef(smallrotation2 * (((float)(j)) / drawhowmany) + lastdrawnsmallrotation2 * (1 - ((float)(j)) / drawhowmany), 0, 1, 0);
997
998                 if (owner != -1) {
999                     if (Person::players[owner]->animTarget == staffhitanim || Person::players[owner]->animCurrent == staffhitanim || Person::players[owner]->animTarget == staffhitreversedanim || Person::players[owner]->animCurrent == staffhitreversedanim) {
1000                         glTranslatef(0, 0, -.3);
1001                     }
1002                     if (Person::players[owner]->animTarget == staffgroundsmashanim || Person::players[owner]->animCurrent == staffgroundsmashanim || Person::players[owner]->animTarget == staffspinhitreversedanim || Person::players[owner]->animCurrent == staffspinhitreversedanim || Person::players[owner]->animTarget == staffspinhitanim || Person::players[owner]->animCurrent == staffspinhitanim) {
1003                         glTranslatef(0, 0, -.1);
1004                     }
1005                 }
1006
1007                 glEnable(GL_LIGHTING);
1008                 switch (type) {
1009                 case knife:
1010                     if (!bloody || !bloodtoggle)
1011                         throwingknifemodel.drawdifftex(knifetextureptr);
1012                     if (bloodtoggle) {
1013                         if (bloody == 1)
1014                             throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
1015                         if (bloody == 2)
1016                             throwingknifemodel.drawdifftex(bloodknifetextureptr);
1017                     }
1018                     break;
1019                 case sword:
1020                     if (!bloody || !bloodtoggle)
1021                         swordmodel.drawdifftex(swordtextureptr);
1022                     if (bloodtoggle) {
1023                         if (bloody == 1)
1024                             swordmodel.drawdifftex(lightbloodswordtextureptr);
1025                         if (bloody == 2)
1026                             swordmodel.drawdifftex(bloodswordtextureptr);
1027                     }
1028                     break;
1029                 case staff:
1030                     staffmodel.drawdifftex(stafftextureptr);
1031                     break;
1032                 }
1033
1034                 glPopMatrix();
1035             }
1036
1037             lastdrawnposition = position;
1038             lastdrawntippoint = tippoint;
1039             lastdrawnrotation1 = rotation1;
1040             lastdrawnrotation2 = rotation2;
1041             lastdrawnrotation3 = rotation3;
1042             lastdrawnbigrotation = bigrotation;
1043             lastdrawnbigtilt = bigtilt;
1044             lastdrawnbigtilt2 = bigtilt2;
1045             lastdrawnsmallrotation = smallrotation;
1046             lastdrawnsmallrotation2 = smallrotation2;
1047             if (owner != -1)
1048                 lastdrawnanim = Person::players[owner]->animCurrent;
1049         }
1050         if (owner != -1) {
1051             glMatrixMode(GL_MODELVIEW);
1052             glPushMatrix();
1053             glLoadIdentity();
1054             glTranslatef(position.x, position.y - .02, position.z);
1055             glRotatef(bigrotation, 0, 1, 0);
1056             glRotatef(bigtilt2, 1, 0, 0);
1057             glRotatef(bigtilt, 0, 0, 1);
1058             glRotatef(-rotation1 + 90, 0, 1, 0);
1059             glRotatef(-rotation2 + 90, 0, 0, 1);
1060             glRotatef(-rotation3, 0, 1, 0);
1061             glRotatef(smallrotation, 1, 0, 0);
1062             glRotatef(smallrotation2, 0, 1, 0);
1063             glTranslatef(0, 0, length);
1064             glGetFloatv(GL_MODELVIEW_MATRIX, M);
1065             tippoint.x = M[12];
1066             tippoint.y = M[13];
1067             tippoint.z = M[14];
1068             glPopMatrix();
1069         }
1070     }
1071 }
1072
1073 void Weapon::drop(XYZ v, XYZ tv, bool sethitsomething)
1074 {
1075     owner = -1;
1076     velocity = v;
1077     tipvelocity = tv;
1078     missed = 1;
1079     if (sethitsomething) {
1080         hitsomething = 0;
1081     }
1082     freetime = 0;
1083     firstfree = 1;
1084     physics = 1;
1085 }
1086
1087 void Weapon::thrown(XYZ v, bool sethitsomething)
1088 {
1089     drop(v, v, sethitsomething);
1090     missed = 0;
1091     physics = 0;
1092 }
1093
1094 int Weapons::Draw()
1095 {
1096     glAlphaFunc(GL_GREATER, 0.9);
1097     glEnable(GL_TEXTURE_2D);
1098     glEnable(GL_BLEND);
1099     glEnable(GL_CULL_FACE);
1100     glCullFace(GL_FRONT);
1101     glDepthMask(1);
1102
1103     for (std::vector<Weapon>::iterator weapon = begin(); weapon != end(); ++weapon) {
1104         weapon->Draw();
1105     }
1106     return 0;
1107 }
1108
1109 Weapons::Weapons()
1110 {
1111 }
1112
1113 Weapons::~Weapons()
1114 {
1115     Weapon::stafftextureptr.destroy();
1116     Weapon::knifetextureptr.destroy();
1117     Weapon::lightbloodknifetextureptr.destroy();
1118     Weapon::bloodknifetextureptr.destroy();
1119     Weapon::swordtextureptr.destroy();
1120     Weapon::lightbloodswordtextureptr.destroy();
1121     Weapon::bloodswordtextureptr.destroy();
1122 }
1123