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