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