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