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