]> git.jsancho.org Git - lugaru.git/blob - Source/GameTick.cpp
MAJOR cleanup
[lugaru.git] / Source / GameTick.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21
22 #if PLATFORM_UNIX
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #else
27 #include <direct.h>
28 #endif
29
30 #include <ctime>
31 #include "Game.h"
32 #include "openal_wrapper.h"
33 #include "Settings.h"
34 #include "Input.h"
35 #include "Animation.h"
36 #include "Awards.h"
37
38 using namespace std;
39
40 // Added more evilness needed for MSVC
41 #ifdef _MSC_VER
42         #define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
43         #define snprintf(buf, size, format, ...) _sprintf_p(buf, size, format)
44 #endif
45
46
47 extern float multiplier;
48 extern XYZ viewer;
49 extern int environment;
50 extern Terrain terrain;
51 extern float screenwidth,screenheight;
52 extern float gravity;
53 extern int detail;
54 extern float texdetail;
55 extern Objects objects;
56 extern int slomo;
57 extern float slomodelay;
58 extern bool floatjump;
59 extern float volume;
60 extern Light light;
61 extern float camerashake;
62 extern float woozy;
63 extern float blackout;
64 extern bool cellophane;
65 extern bool musictoggle;
66 extern int difficulty;
67 extern int bloodtoggle;
68 extern bool invertmouse;
69 extern float windvar;
70 extern float precipdelay;
71 extern XYZ viewerfacing;
72 extern bool ambientsound;
73 extern bool mousejump;
74 extern float viewdistance;
75 extern bool freeze;
76 extern bool keyboardfrozen;
77 extern bool loadingstuff;
78 extern XYZ windvector;
79 extern bool debugmode;
80 static int music1;
81 extern int mainmenu;
82 extern bool visibleloading;
83 extern int loadscreencolor;
84 extern XYZ envsound[30];
85 extern float envsoundvol[30];
86 extern int numenvsounds;
87 extern float envsoundlife[30];
88 extern float usermousesensitivity;
89 extern bool ismotionblur;
90 extern bool showdamagebar; // (des)activate the damage bar
91 extern bool decals;
92 extern float tintr,tintg,tintb;
93 extern bool skyboxtexture;
94 extern float skyboxr;
95 extern float skyboxg;
96 extern float skyboxb;
97 extern float skyboxlightr;
98 extern float skyboxlightg;
99 extern float skyboxlightb;
100 extern float fadestart;
101 extern float slomospeed;
102 extern float slomofreq;
103 extern int tutoriallevel;
104 extern float smoketex;
105 extern float tutorialstagetime;
106 extern int tutorialstage;
107 extern float tutorialmaxtime;
108 extern float tutorialsuccess;
109 extern bool againbonus;
110 extern bool reversaltrain;
111 extern bool canattack;
112 extern bool cananger;
113 extern float damagedealt;
114 extern int maptype;
115 extern int editoractive;
116 extern int editorpathtype;
117
118 extern float hostiletime;
119
120 extern bool gamestarted;
121
122 extern int numhotspots;
123 extern int winhotspot;
124 extern int windialogue;
125 extern int killhotspot;
126 extern XYZ hotspot[40];
127 extern int hotspottype[40];
128 extern float hotspotsize[40];
129 extern char hotspottext[40][256];
130 extern int currenthotspot;
131
132 extern int hostile;
133
134 extern bool stillloading;
135 extern bool winfreeze;
136
137 extern bool campaign;
138
139 static const char *rabbitskin[] = {
140 ":Data:Textures:Fur3.jpg",
141 ":Data:Textures:Fur.jpg",
142 ":Data:Textures:Fur2.jpg",
143 ":Data:Textures:Lynx.jpg",
144 ":Data:Textures:Otter.jpg",
145 ":Data:Textures:Opal.jpg",
146 ":Data:Textures:Sable.jpg",
147 ":Data:Textures:Chocolate.jpg",
148 ":Data:Textures:BW2.jpg",
149 ":Data:Textures:WB2.jpg"
150 };
151
152 static const char *wolfskin[] = {
153 ":Data:Textures:Wolf.jpg",
154 ":Data:Textures:Darkwolf.jpg",
155 ":Data:Textures:Snowwolf.jpg"
156 };
157
158 #define STATIC_ASSERT(x) extern int s_a_dummy[2 * (!!(x)) - 1];
159 STATIC_ASSERT (rabbittype == 0 && wolftype == 1)
160
161 static const char **creatureskin[] = {rabbitskin, wolfskin};
162
163 /* Return true if PFX is a prefix of STR (case-insensitive).  */
164 static bool stripfx(const char *str, const char *pfx)
165 {
166   return !strncasecmp(str, pfx, strlen(pfx));
167 }
168
169 static const char *cmd_names[] = {
170 #define DECLARE_COMMAND(cmd) #cmd " ",
171 #include "ConsoleCmds.h"
172 #undef  DECLARE_COMMAND
173 };
174
175 typedef void (*console_handler)(Game *game, const char *args);
176
177 #define DECLARE_COMMAND(cmd) static void ch_##cmd(Game *game, const char *args);
178 #include "ConsoleCmds.h"
179 #undef  DECLARE_COMMAND
180
181 static console_handler cmd_handlers[] = {
182 #define DECLARE_COMMAND(cmd) ch_##cmd,
183 #include "ConsoleCmds.h"
184 #undef  DECLARE_COMMAND
185 };
186
187
188
189 // added utility functions -sf17k =============================================================
190
191 //TODO: try to hide these variables completely with a better interface
192 inline void setAnimation(int playerid,int animation){
193     player[playerid].targetanimation=animation;
194     player[playerid].targetframe=0;
195     player[playerid].target=0;
196 }
197
198 //TODO: this is incorrect but I'm afraid to change it and break something,
199 //probably causes quirky behavior that I might want to preserve
200 inline float roughDirection(XYZ vec){
201     Normalise(&vec);
202     float angle=-asin(-vec.x)*180/M_PI;
203     if(vec.z<0)
204         angle=180-angle;
205     return angle;
206 }
207 inline float roughDirectionTo(XYZ start, XYZ end){
208     return roughDirection(end-start);
209 }
210
211 //TODO: gotta be a better way
212 inline float pitch(XYZ vec){
213     Normalise(&vec);
214     return -asin(vec.y)*180/M_PI;
215 }
216 inline float pitchTo(XYZ start, XYZ end){
217     return pitch(end-start);
218 }
219
220 //change these to a Person method
221 inline Joint& playerJoint(int playerid, int bodypart){
222     return player[playerid].skeleton.joints[player[playerid].skeleton.jointlabels[bodypart]]; }
223 inline Joint& playerJoint(Person* pplayer, int bodypart){
224     return pplayer->skeleton.joints[pplayer->skeleton.jointlabels[bodypart]]; }
225
226 inline float sq(float n){ return n*n; }
227
228 inline float stepTowardf(float from, float to, float by){
229     if(fabs(from-to)<by) return to;
230     else if(from>to) return from-by;
231     else return from+by;
232 }
233
234 void playdialogueboxsound(){
235     XYZ temppos;
236     temppos=player[participantfocus[whichdialogue][indialogue]].coords;
237     temppos=temppos-viewer;
238     Normalise(&temppos);
239     temppos+=viewer;
240
241     int sound=-1;
242     switch(dialogueboxsound[whichdialogue][indialogue]){
243         case -6: sound=alarmsound; break;
244         case -4: sound=consolefailsound; break;
245         case -3: sound=consolesuccesssound; break;
246         case -2: sound=firestartsound; break;
247         case -1: sound=fireendsound; break;
248         case 1: sound=rabbitchitter; break;
249         case 2: sound=rabbitchitter2; break;
250         case 3: sound=rabbitpainsound; break;
251         case 4: sound=rabbitpain1sound; break;
252         case 5: sound=rabbitattacksound; break;
253         case 6: sound=rabbitattack2sound; break;
254         case 7: sound=rabbitattack3sound; break;
255         case 8: sound=rabbitattack4sound; break;
256         case 9: sound=growlsound; break;
257         case 10: sound=growl2sound; break;
258         case 11: sound=snarlsound; break;
259         case 12: sound=snarl2sound; break;
260         case 13: sound=barksound; break;
261         case 14: sound=bark2sound; break;
262         case 15: sound=bark3sound; break;
263         case 16: sound=barkgrowlsound; break;
264         default: break;
265     }
266     if(sound!=-1)
267         emit_sound_at(sound, temppos);
268 }
269
270 // end added utility functions ================================================================
271
272
273
274 static void ch_quit(Game *game, const char *args)
275 {
276   game->tryquit = 1;
277 }
278
279 static void ch_map(Game *game, const char *args)
280 {
281   game->Loadlevel(args);
282   game->whichlevel = -2;
283   campaign = 0;
284 }
285
286 static void ch_save(Game *game, const char *args)
287 {
288   char buf[64];
289   int i, j, k, l, m, templength;
290   float headprop, bodyprop, armprop, legprop;
291   snprintf(buf, 63, ":Data:Maps:%s", args);
292
293
294   int mapvers = 12;;
295
296   FILE                  *tfile;
297   tfile=fopen( ConvertFileName(buf), "wb" );
298   fpackf(tfile, "Bi", mapvers);
299   fpackf(tfile, "Bi", maptype);
300   fpackf(tfile, "Bi", hostile);
301   fpackf(tfile, "Bf Bf", viewdistance, fadestart);
302   fpackf(tfile, "Bb Bf Bf Bf", skyboxtexture, skyboxr, skyboxg, skyboxb);
303   fpackf(tfile, "Bf Bf Bf", skyboxlightr, skyboxlightg, skyboxlightb);
304   fpackf(tfile, "Bf Bf Bf Bf Bf Bi", player[0].coords.x, player[0].coords.y, player[0].coords.z, player[0].rotation, player[0].targetrotation, player[0].num_weapons);
305   if(player[0].num_weapons>0&&player[0].num_weapons<5)
306     for(int j=0;j<player[0].num_weapons;j++){
307       fpackf(tfile, "Bi", weapons.type[player[0].weaponids[j]]);
308     }
309
310   fpackf(tfile, "Bf Bf Bf", player[0].armorhead, player[0].armorhigh, player[0].armorlow);
311   fpackf(tfile, "Bf Bf Bf", player[0].protectionhead, player[0].protectionhigh, player[0].protectionlow);
312   fpackf(tfile, "Bf Bf Bf", player[0].metalhead, player[0].metalhigh, player[0].metallow);
313   fpackf(tfile, "Bf Bf", player[0].power, player[0].speedmult);
314
315   fpackf(tfile, "Bi", player[0].numclothes);
316
317   fpackf(tfile, "Bi Bi", player[0].whichskin, player[0].creature);
318
319   fpackf(tfile, "Bi", numdialogues);
320         for(int k=0;k<numdialogues;k++){
321                 fpackf(tfile, "Bi", numdialogueboxes[k]);
322                 fpackf(tfile, "Bi", dialoguetype[k]);
323                 for(int l=0;l<10;l++){
324                         fpackf(tfile, "Bf Bf Bf", participantlocation[k][l].x, participantlocation[k][l].y, participantlocation[k][l].z);
325                         fpackf(tfile, "Bf", participantrotation[k][l]);
326                 }
327                 for(int l=0;l<numdialogueboxes[k];l++){
328                         fpackf(tfile, "Bi", dialogueboxlocation[k][l]);
329                         fpackf(tfile, "Bf", dialogueboxcolor[k][l][0]);
330                         fpackf(tfile, "Bf", dialogueboxcolor[k][l][1]);
331                         fpackf(tfile, "Bf", dialogueboxcolor[k][l][2]);
332                         fpackf(tfile, "Bi", dialogueboxsound[k][l]);
333
334                         templength=strlen(dialoguetext[k][l]);
335                         fpackf(tfile, "Bi",(templength));
336                         for(int m=0;m<templength;m++){
337                                 fpackf(tfile, "Bb", dialoguetext[k][l][m]);
338                                 if(dialoguetext[k][l][m]=='\0')break;
339                         }
340
341                         templength=strlen(dialoguename[k][l]);
342                         fpackf(tfile, "Bi",templength);
343                         for(int m=0;m<templength;m++){
344                                 fpackf(tfile, "Bb", dialoguename[k][l][m]);
345                                 if(dialoguename[k][l][m]=='\0')break;
346                         }
347
348                         fpackf(tfile, "Bf Bf Bf", dialoguecamera[k][l].x, dialoguecamera[k][l].y, dialoguecamera[k][l].z);
349                         fpackf(tfile, "Bi", participantfocus[k][l]);
350                         fpackf(tfile, "Bi", participantaction[k][l]);
351
352                         for(int m=0;m<10;m++)
353                                 fpackf(tfile, "Bf Bf Bf", participantfacing[k][l][m].x, participantfacing[k][l][m].y, participantfacing[k][l][m].z);
354
355                         fpackf(tfile, "Bf Bf",dialoguecamerarotation[k][l],dialoguecamerarotation2[k][l]);
356                 }
357         }
358
359         for(int k=0;k<player[0].numclothes;k++){
360                 templength=strlen(player[0].clothes[k]);
361                 fpackf(tfile, "Bi", templength);
362                 for(int l=0;l<templength;l++)
363                         fpackf(tfile, "Bb", player[0].clothes[k][l]);
364                 fpackf(tfile, "Bf Bf Bf", player[0].clothestintr[k], player[0].clothestintg[k], player[0].clothestintb[k]);
365         }
366
367   fpackf(tfile, "Bi", environment);
368
369   fpackf(tfile, "Bi", objects.numobjects);
370
371     for(int k=0;k<objects.numobjects;k++){
372       fpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", objects.type[k], objects.rotation[k], objects.rotation2[k], objects.position[k].x, objects.position[k].y, objects.position[k].z, objects.scale[k]);
373     }
374
375   fpackf(tfile, "Bi", numhotspots);
376         for(int i=0;i<numhotspots;i++){
377                 fpackf(tfile, "Bi Bf Bf Bf Bf", hotspottype[i],hotspotsize[i],hotspot[i].x,hotspot[i].y,hotspot[i].z);
378                 templength=strlen(hotspottext[i]);
379                 fpackf(tfile, "Bi",templength);
380                 for(int l=0;l<templength;l++)
381                         fpackf(tfile, "Bb", hotspottext[i][l]);
382         }
383
384   fpackf(tfile, "Bi", numplayers);
385   if(numplayers<maxplayers)
386     for(int j=1;j<numplayers;j++){
387                 fpackf(tfile, "Bi Bi Bf Bf Bf Bi Bi Bf Bb Bf", player[j].whichskin, player[j].creature, player[j].coords.x, player[j].coords.y, player[j].coords.z, player[j].num_weapons, player[j].howactive, player[j].scale, player[j].immobile, player[j].rotation);
388                 if(player[j].num_weapons<5)
389                         for(int k=0;k<player[j].num_weapons;k++){
390                                 fpackf(tfile, "Bi", weapons.type[player[j].weaponids[k]]);
391                         }
392                 if(player[j].numwaypoints<30){
393                         fpackf(tfile, "Bi", player[j].numwaypoints);
394                         for(int k=0;k<player[j].numwaypoints;k++){
395                                 fpackf(tfile, "Bf", player[j].waypoints[k].x);
396                                 fpackf(tfile, "Bf", player[j].waypoints[k].y);
397                                 fpackf(tfile, "Bf", player[j].waypoints[k].z);
398                                 fpackf(tfile, "Bi", player[j].waypointtype[k]);
399                         }
400                         fpackf(tfile, "Bi", player[j].waypoint);
401                 } else {
402                         player[j].numwaypoints=0;
403                         player[j].waypoint=0;
404                         fpackf(tfile, "Bi Bi Bi", player[j].numwaypoints, player[j].waypoint, player[j].waypoint);
405                 }
406
407                 fpackf(tfile, "Bf Bf Bf", player[j].armorhead, player[j].armorhigh, player[j].armorlow);
408                 fpackf(tfile, "Bf Bf Bf", player[j].protectionhead, player[j].protectionhigh, player[j].protectionlow);
409                 fpackf(tfile, "Bf Bf Bf", player[j].metalhead, player[j].metalhigh, player[j].metallow);
410                 fpackf(tfile, "Bf Bf", player[j].power, player[j].speedmult);
411
412                 if(player[j].creature==wolftype) {
413                         headprop=player[j].proportionhead.x/1.1;
414                         bodyprop=player[j].proportionbody.x/1.1;
415                         armprop=player[j].proportionarms.x/1.1;
416                         legprop=player[j].proportionlegs.x/1.1;
417                 } else if(player[j].creature==rabbittype){
418                         headprop=player[j].proportionhead.x/1.2;
419                         bodyprop=player[j].proportionbody.x/1.05;
420                         armprop=player[j].proportionarms.x/1.00;
421                         legprop=player[j].proportionlegs.x/1.1;
422                 }
423
424                 fpackf(tfile, "Bf Bf Bf Bf", headprop, bodyprop, armprop, legprop);
425
426                 fpackf(tfile, "Bi", player[j].numclothes);
427                 if(player[j].numclothes)
428                         for(int k=0;k<player[j].numclothes;k++){
429                                 int templength;
430                                 templength=strlen(player[j].clothes[k]);
431                                 fpackf(tfile, "Bi", templength);
432                                 for(int l=0;l<templength;l++)
433                                         fpackf(tfile, "Bb", player[j].clothes[k][l]);
434                                 fpackf(tfile, "Bf Bf Bf", player[j].clothestintr[k], player[j].clothestintg[k], player[j].clothestintb[k]);
435                         }
436     }
437
438   fpackf(tfile, "Bi", game->numpathpoints);
439         for(int j=0;j<game->numpathpoints;j++){
440                 fpackf(tfile, "Bf Bf Bf Bi", game->pathpoint[j].x, game->pathpoint[j].y, game->pathpoint[j].z, game->numpathpointconnect[j]);
441                 for(int k=0;k<game->numpathpointconnect[j];k++){
442                         fpackf(tfile, "Bi", game->pathpointconnect[j][k]);
443                 }
444         }
445
446   fpackf(tfile, "Bf Bf Bf Bf", game->mapcenter.x, game->mapcenter.y, game->mapcenter.z, game->mapradius);
447
448   fclose(tfile);
449 }
450
451 static void ch_cellar(Game *game, const char *args)
452 {
453   game->LoadTextureSave(":Data:Textures:Furdarko.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
454 }
455
456 static void ch_tint(Game *game, const char *args)
457 {
458   sscanf(args, "%f%f%f", &tintr, &tintg, &tintb);
459 }
460
461 static void ch_tintr(Game *game, const char *args)
462 {
463   tintr = atof(args);
464 }
465
466 static void ch_tintg(Game *game, const char *args)
467 {
468   tintg = atof(args);
469 }
470
471 static void ch_tintb(Game *game, const char *args)
472 {
473   tintb = atof(args);
474 }
475
476 static void ch_speed(Game *game, const char *args)
477 {
478   player[0].speedmult = atof(args);
479 }
480
481 static void ch_strength(Game *game, const char *args)
482 {
483   player[0].power = atof(args);
484 }
485
486 static void ch_power(Game *game, const char *args)
487 {
488   player[0].power = atof(args);
489 }
490
491 static void ch_size(Game *game, const char *args)
492 {
493   player[0].scale = atof(args) * .2;
494 }
495
496 static int find_closest()
497 {
498   int closest = 0;
499   float closestdist = 1.0/0.0;
500
501   for (int i = 1; i < numplayers; i++) {
502     float distance;
503     distance = findDistancefast(&player[i].coords,&player[0].coords);
504     if (distance < closestdist) {
505       closestdist = distance;
506       closest = i;
507     }
508   }
509   return closest;
510 }
511
512 static void ch_sizenear(Game *game, const char *args)
513 {
514   int closest = find_closest();
515
516   if (closest)
517     player[closest].scale = atof(args) * .2;
518 }
519
520 static void set_proportion(int pnum, const char *args)
521 {
522   float headprop,bodyprop,armprop,legprop;
523
524   sscanf(args, "%f%f%f%f", &headprop, &bodyprop, &armprop, &legprop);
525
526   if(player[pnum].creature==wolftype){
527     player[pnum].proportionhead=1.1*headprop;
528     player[pnum].proportionbody=1.1*bodyprop;
529     player[pnum].proportionarms=1.1*armprop;
530     player[pnum].proportionlegs=1.1*legprop;
531   } else if(player[pnum].creature==rabbittype){
532     player[pnum].proportionhead=1.2*headprop;
533     player[pnum].proportionbody=1.05*bodyprop;
534     player[pnum].proportionarms=1.00*armprop;
535     player[pnum].proportionlegs=1.1*legprop;
536     player[pnum].proportionlegs.y=1.05*legprop;
537   }
538 }
539
540 static void ch_proportion(Game *game, const char *args)
541 {
542   set_proportion(0, args);
543 }
544
545 static void ch_proportionnear(Game *game, const char *args)
546 {
547   int closest = find_closest();
548   if (closest)
549     set_proportion(closest, args);
550 }
551
552 static void set_protection(int pnum, const char *args)
553 {
554   float head, high, low;
555   sscanf(args, "%f%f%f", &head, &high, &low);
556
557   player[pnum].protectionhead = head;
558   player[pnum].protectionhigh = high;
559   player[pnum].protectionlow  = low;
560 }
561
562 static void ch_protection(Game *game, const char *args)
563 {
564   set_protection(0, args);
565 }
566
567 static void ch_protectionnear(Game *game, const char *args)
568 {
569   int closest = find_closest();
570   if (closest)
571     set_protection(closest, args);
572 }
573
574 static void set_armor(int pnum, const char *args)
575 {
576   float head, high, low;
577   sscanf(args, "%f%f%f", &head, &high, &low);
578
579   player[pnum].armorhead = head;
580   player[pnum].armorhigh = high;
581   player[pnum].armorlow  = low;
582 }
583
584 static void ch_armor(Game *game, const char *args)
585 {
586   set_armor(0, args);
587 }
588
589 static void ch_armornear(Game *game, const char *args)
590 {
591   int closest = find_closest();
592   if (closest)
593     set_armor(closest, args);
594 }
595
596 static void ch_protectionreset(Game *game, const char *args)
597 {
598   set_protection(0, "1 1 1");
599   set_armor(0, "1 1 1");
600 }
601
602 static void set_metal(int pnum, const char *args)
603 {
604   float head, high, low;
605   sscanf(args, "%f%f%f", &head, &high, &low);
606
607   player[pnum].metalhead = head;
608   player[pnum].metalhigh = high;
609   player[pnum].metallow  = low;
610 }
611
612 static void ch_metal(Game *game, const char *args)
613 {
614   set_metal(0, args);
615 }
616
617 static void set_noclothes(int pnum, Game *game, const char *args)
618 {
619   player[pnum].numclothes = 0;
620   game->LoadTextureSave(creatureskin[player[pnum].creature][player[pnum].whichskin],
621                         &player[pnum].skeleton.drawmodel.textureptr,1,
622                         &player[pnum].skeleton.skinText[0],&player[pnum].skeleton.skinsize);
623 }
624
625 static void ch_noclothes(Game *game, const char *args)
626 {
627   set_noclothes(0, game, args);
628 }
629
630 static void ch_noclothesnear(Game *game, const char *args)
631 {
632   int closest = find_closest();
633   if (closest)
634     set_noclothes(closest, game, args);
635 }
636
637
638 static void set_clothes(int pnum, Game *game, const char *args)
639 {
640   char buf[64];
641   snprintf(buf, 63, ":Data:Textures:%s.png", args);
642
643   if (!game->AddClothes(buf,0,1,&player[pnum].skeleton.skinText[pnum],&player[pnum].skeleton.skinsize))
644     return;
645
646   player[pnum].DoMipmaps();
647   strcpy(player[pnum].clothes[player[pnum].numclothes],buf);
648   player[pnum].clothestintr[player[pnum].numclothes]=tintr;
649   player[pnum].clothestintg[player[pnum].numclothes]=tintg;
650   player[pnum].clothestintb[player[pnum].numclothes]=tintb;
651   player[pnum].numclothes++;
652 }
653
654 static void ch_clothes(Game *game, const char *args)
655 {
656   set_clothes(0, game, args);
657 }
658
659 static void ch_clothesnear(Game *game, const char *args)
660 {
661   int closest = find_closest();
662   if (closest)
663     set_clothes(closest, game, args);
664 }
665
666 static void ch_belt(Game *game, const char *args)
667 {
668   player[0].skeleton.clothes = !player[0].skeleton.clothes;
669 }
670
671
672 static void ch_cellophane(Game *game, const char *args)
673 {
674   cellophane = !cellophane;
675   float mul = cellophane ? 0 : 1;
676
677   for (int i = 0; i < numplayers; i++) {
678     player[i].proportionhead.z = player[i].proportionhead.x * mul;
679     player[i].proportionbody.z = player[i].proportionbody.x * mul;
680     player[i].proportionarms.z = player[i].proportionarms.x * mul;
681     player[i].proportionlegs.z = player[i].proportionlegs.x * mul;
682   }
683 }
684
685 static void ch_funnybunny(Game *game, const char *args)
686 {
687   player[0].skeleton.id=0;
688   player[0].skeleton.Load(":Data:Skeleton:Basic Figure",":Data:Skeleton:Basic Figurelow",
689                           ":Data:Skeleton:Rabbitbelt",":Data:Models:Body.solid",
690                           ":Data:Models:Body2.solid",":Data:Models:Body3.solid",
691                           ":Data:Models:Body4.solid",":Data:Models:Body5.solid",
692                           ":Data:Models:Body6.solid",":Data:Models:Body7.solid",
693                           ":Data:Models:Bodylow.solid",":Data:Models:Belt.solid",1);
694   game->LoadTextureSave(":Data:Textures:fur3.jpg",&player[0].skeleton.drawmodel.textureptr,1,
695                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
696   player[0].creature=rabbittype;
697   player[0].scale=.2;
698   player[0].headless=0;
699   player[0].damagetolerance=200;
700   set_proportion(0, "1 1 1 1");
701 }
702
703 static void ch_wolfie(Game *game, const char *args)
704 {
705   player[0].skeleton.id=0;
706   player[0].skeleton.Load(":Data:Skeleton:Basic Figure Wolf",":Data:Skeleton:Basic Figure Wolf Low",
707                           ":Data:Skeleton:Rabbitbelt",":Data:Models:Wolf.solid",
708                           ":Data:Models:Wolf2.solid",":Data:Models:Wolf3.solid",
709                           ":Data:Models:Wolf4.solid",":Data:Models:Wolf5.solid",
710                           ":Data:Models:Wolf6.solid",":Data:Models:Wolf7.solid",
711                           ":Data:Models:Wolflow.solid",":Data:Models:Belt.solid",0);
712   game->LoadTextureSave(":Data:Textures:Wolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,
713                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
714   player[0].creature=wolftype;
715   player[0].damagetolerance=300;
716   set_proportion(0, "1 1 1 1");
717 }
718
719 static void ch_wolfieisgod(Game *game, const char *args)
720 {
721   ch_wolfie(game, args);
722 }
723
724 static void ch_wolf(Game *game, const char *args)
725 {
726   game->LoadTextureSave(":Data:Textures:Wolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,
727                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
728 }
729
730 static void ch_snowwolf(Game *game, const char *args)
731 {
732   game->LoadTextureSave(":Data:Textures:SnowWolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,
733                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
734 }
735
736 static void ch_darkwolf(Game *game, const char *args)
737 {
738   game->LoadTextureSave(":Data:Textures:DarkWolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,
739                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
740 }
741
742 static void ch_lizardwolf(Game *game, const char *args)
743 {
744   game->LoadTextureSave(":Data:Textures:Lizardwolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,
745                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
746 }
747
748 static void ch_white(Game *game, const char *args)
749 {
750   game->LoadTextureSave(":Data:Textures:fur.jpg",&player[0].skeleton.drawmodel.textureptr,1,
751                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
752 }
753
754 static void ch_brown(Game *game, const char *args)
755 {
756   game->LoadTextureSave(":Data:Textures:fur3.jpg",&player[0].skeleton.drawmodel.textureptr,1,
757                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
758 }
759
760 static void ch_black(Game *game, const char *args)
761 {
762   game->LoadTextureSave(":Data:Textures:fur2.jpg",&player[0].skeleton.drawmodel.textureptr,1,
763                         &player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
764 }
765
766 static void ch_sizemin(Game *game, const char *args)
767 {
768   for (int i = 1; i < numplayers; i++)
769     if (player[i].scale < 0.8 * 0.2)
770       player[i].scale = 0.8 * 0.2;
771 }
772
773 static void ch_tutorial(Game *game, const char *args)
774 {
775   tutoriallevel = atoi(args);
776 }
777
778 static void ch_hostile(Game *game, const char *args)
779 {
780   hostile = atoi(args);
781 }
782
783 static void ch_indemo(Game *game, const char *args)
784 {
785   game->indemo=1;
786   hotspot[numhotspots]=player[0].coords;
787   hotspotsize[numhotspots]=0;
788   hotspottype[numhotspots]=-111;
789   strcpy(hotspottext[numhotspots],"mapname");
790   numhotspots++;
791 }
792
793 static void ch_notindemo(Game *game, const char *args)
794 {
795   game->indemo=0;
796   numhotspots--;
797 }
798
799 static void ch_type(Game *game, const char *args)
800 {
801   int n = sizeof(editortypenames) / sizeof(editortypenames[0]);
802         for (int i = 0; i < n; i++)
803                 if (stripfx(args, editortypenames[i])) {
804                         editoractive = i;
805                         break;
806                 }
807 }
808
809 static void ch_path(Game *game, const char *args)
810 {
811   int n = sizeof(pathtypenames) / sizeof(pathtypenames[0]);
812   for (int i = 0; i < n; i++)
813     if (stripfx(args, pathtypenames[i])) {
814                 editorpathtype = i;
815                 break;
816     }
817 }
818
819 static void ch_hs(Game *game, const char *args)
820 {
821   hotspot[numhotspots]=player[0].coords;
822
823   float size;
824   int type, shift;
825   sscanf(args, "%f%d %n", &size, &type, &shift);
826
827   hotspotsize[numhotspots] = size;
828   hotspottype[numhotspots] = type;
829
830   strcpy(hotspottext[numhotspots], args + shift);
831   strcat(hotspottext[numhotspots], "\n");
832
833   numhotspots++;
834 }
835
836 static void ch_dialogue(Game *game, const char *args)
837 {
838   int dlg;
839   char buf1[32], buf2[64];
840
841   sscanf(args, "%d %31s", &dlg, buf1);
842   snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
843
844   dialoguetype[numdialogues] = dlg;
845
846   memset(dialoguetext[numdialogues], 0, sizeof(dialoguetext[numdialogues]));
847   memset(dialoguename[numdialogues], 0, sizeof(dialoguename[numdialogues]));
848
849   ifstream ipstream(ConvertFileName(buf2));
850   ipstream.ignore(256,':');
851   ipstream >> numdialogueboxes[numdialogues];
852   for(int i=0;i<numdialogueboxes[numdialogues];i++){
853     ipstream.ignore(256,':');
854     ipstream.ignore(256,':');
855     ipstream.ignore(256,' ');
856     ipstream >> dialogueboxlocation[numdialogues][i];
857     ipstream.ignore(256,':');
858     ipstream >> dialogueboxcolor[numdialogues][i][0];
859     ipstream >> dialogueboxcolor[numdialogues][i][1];
860     ipstream >> dialogueboxcolor[numdialogues][i][2];
861     ipstream.ignore(256,':');
862     ipstream.getline(dialoguename[numdialogues][i],64);
863     ipstream.ignore(256,':');
864     ipstream.ignore(256,' ');
865     ipstream.getline(dialoguetext[numdialogues][i],128);
866     for(int j=0;j<128;j++){
867       if(dialoguetext[numdialogues][i][j]=='\\')dialoguetext[numdialogues][i][j]='\n';
868     }
869     ipstream.ignore(256,':');
870     ipstream >> dialogueboxsound[numdialogues][i];
871   }
872
873   for(int i=0;i<numdialogueboxes[numdialogues];i++){
874     for(int j=0;j<numplayers;j++){
875       participantfacing[numdialogues][i][j]=player[j].facing;
876     }
877   }
878   ipstream.close();
879
880   directing=1;
881   indialogue=0;
882   whichdialogue=numdialogues;
883
884   numdialogues++;
885 }
886
887 static void ch_fixdialogue(Game *game, const char *args)
888 {
889   char buf1[32], buf2[64];
890   int whichdi;
891
892   sscanf(args, "%d %31s", &whichdi, buf1);
893   snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
894
895   memset(dialoguetext[whichdi], 0, sizeof(dialoguetext[whichdi]));
896   memset(dialoguename[whichdi], 0, sizeof(dialoguename[whichdi]));
897
898   ifstream ipstream(ConvertFileName(buf2));
899   ipstream.ignore(256,':');
900   ipstream >> numdialogueboxes[whichdi];
901   for(int i=0;i<numdialogueboxes[whichdi];i++){
902     ipstream.ignore(256,':');
903     ipstream.ignore(256,':');
904     ipstream.ignore(256,' ');
905     ipstream >> dialogueboxlocation[whichdi][i];
906     ipstream.ignore(256,':');
907     ipstream >> dialogueboxcolor[whichdi][i][0];
908     ipstream >> dialogueboxcolor[whichdi][i][1];
909     ipstream >> dialogueboxcolor[whichdi][i][2];
910     ipstream.ignore(256,':');
911     ipstream.getline(dialoguename[whichdi][i],64);
912     ipstream.ignore(256,':');
913     ipstream.ignore(256,' ');
914     ipstream.getline(dialoguetext[whichdi][i],128);
915     for(int j=0;j<128;j++){
916       if(dialoguetext[whichdi][i][j]=='\\')dialoguetext[whichdi][i][j]='\n';
917     }
918     ipstream.ignore(256,':');
919     ipstream >> dialogueboxsound[whichdi][i];
920   }
921
922   ipstream.close();
923 }
924
925 static void ch_fixtype(Game *game, const char *args)
926 {
927   int dlg;
928   sscanf(args, "%d", &dlg);
929   dialoguetype[0] = dlg;
930 }
931
932 static void ch_fixrotation(Game *game, const char *args)
933 {
934   participantrotation[whichdialogue][participantfocus[whichdialogue][indialogue]]=player[participantfocus[whichdialogue][indialogue]].rotation;
935 }
936
937 static void ch_ddialogue(Game *game, const char *args)
938 {
939   if (numdialogues)
940     numdialogues--;
941 }
942
943 static void ch_dhs(Game *game, const char *args)
944 {
945   if (numhotspots)
946     numhotspots--;
947 }
948
949 static void ch_immobile(Game *game, const char *args)
950 {
951   player[0].immobile = 1;
952 }
953
954 static void ch_allimmobile(Game *game, const char *args)
955 {
956   for (int i = 1; i < numplayers; i++)
957     player[i].immobile = 1;
958 }
959
960 static void ch_mobile(Game *game, const char *args)
961 {
962   player[0].immobile = 0;
963 }
964
965 static void ch_default(Game *game, const char *args)
966 {
967   player[0].armorhead=1;
968   player[0].armorhigh=1;
969   player[0].armorlow=1;
970   player[0].protectionhead=1;
971   player[0].protectionhigh=1;
972   player[0].protectionlow=1;
973   player[0].metalhead=1;
974   player[0].metalhigh=1;
975   player[0].metallow=1;
976   player[0].power=1;
977   player[0].speedmult=1;
978   player[0].scale=1;
979
980   if(player[0].creature==wolftype){
981     player[0].proportionhead=1.1;
982     player[0].proportionbody=1.1;
983     player[0].proportionarms=1.1;
984     player[0].proportionlegs=1.1;
985   } else if(player[0].creature==rabbittype){
986     player[0].proportionhead=1.2;
987     player[0].proportionbody=1.05;
988     player[0].proportionarms=1.00;
989     player[0].proportionlegs=1.1;
990     player[0].proportionlegs.y=1.05;
991   }
992
993   player[0].numclothes=0;
994   game->LoadTextureSave(creatureskin[player[0].creature][player[0].whichskin],
995                         &player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],
996                         &player[0].skeleton.skinsize);
997
998   editoractive=typeactive;
999   player[0].immobile=0;
1000 }
1001
1002 static void ch_play(Game *game, const char *args)
1003 {
1004   int dlg;
1005   sscanf(args, "%d", &dlg);
1006   whichdialogue = dlg;
1007
1008   if (whichdialogue >= numdialogues)
1009     return;
1010
1011   for(int i=0;i<numdialogueboxes[whichdialogue];i++){
1012     player[participantfocus[whichdialogue][i]].coords=participantlocation[whichdialogue][participantfocus[whichdialogue][i]];
1013     player[participantfocus[whichdialogue][i]].rotation=participantrotation[whichdialogue][participantfocus[whichdialogue][i]];
1014     player[participantfocus[whichdialogue][i]].targetrotation=participantrotation[whichdialogue][participantfocus[whichdialogue][i]];
1015     player[participantfocus[whichdialogue][i]].velocity=0;
1016     player[participantfocus[whichdialogue][i]].targetanimation=player[participantfocus[whichdialogue][i]].getIdle();
1017     player[participantfocus[whichdialogue][i]].targetframe=0;
1018   }
1019
1020   directing=0;
1021   indialogue=0;
1022
1023   playdialogueboxsound();
1024 }
1025
1026 static void ch_mapkilleveryone(Game *game, const char *args)
1027 {
1028   maptype = mapkilleveryone;
1029 }
1030
1031 static void ch_mapkillmost(Game *game, const char *args)
1032 {
1033   maptype = mapkillmost;
1034 }
1035
1036 static void ch_mapkillsomeone(Game *game, const char *args)
1037 {
1038   maptype = mapkillsomeone;
1039 }
1040
1041 static void ch_mapgosomewhere(Game *game, const char *args)
1042 {
1043   maptype = mapgosomewhere;
1044 }
1045
1046 static void ch_viewdistance(Game *game, const char *args)
1047 {
1048   viewdistance = atof(args)*100;
1049 }
1050
1051 static void ch_fadestart(Game *game, const char *args)
1052 {
1053   fadestart = atof(args);
1054 }
1055
1056 static void ch_slomo(Game *game, const char *args)
1057 {
1058   slomospeed = atof(args);
1059   slomo = !slomo;
1060   slomodelay = 1000;
1061 }
1062
1063 static void ch_slofreq(Game *game, const char *args)
1064 {
1065   slomofreq = atof(args);
1066 }
1067
1068 static void ch_skytint(Game *game, const char *args)
1069 {
1070   sscanf(args, "%f%f%f", &skyboxr, &skyboxg, &skyboxb);
1071
1072   skyboxlightr=skyboxr;
1073   skyboxlightg=skyboxg;
1074   skyboxlightb=skyboxb;
1075
1076   game->SetUpLighting();
1077
1078   terrain.DoShadows();
1079   objects.DoShadows();
1080 }
1081
1082 static void ch_skylight(Game *game, const char *args)
1083 {
1084   sscanf(args, "%f%f%f", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1085
1086   game->SetUpLighting();
1087
1088   terrain.DoShadows();
1089   objects.DoShadows();
1090 }
1091
1092 static void ch_skybox(Game *game, const char *args)
1093 {
1094   skyboxtexture = !skyboxtexture;
1095
1096   game->SetUpLighting();
1097
1098   terrain.DoShadows();
1099   objects.DoShadows();
1100 }
1101
1102 static void cmd_dispatch(Game *game, const char *cmd)
1103 {
1104   int i, n_cmds = sizeof(cmd_names) / sizeof(cmd_names[0]);
1105
1106   for (i = 0; i < n_cmds; i++)
1107     if (stripfx(cmd, cmd_names[i]))
1108       {
1109         cmd_handlers[i](game, cmd + strlen(cmd_names[i]));
1110         break;
1111       }
1112   emit_sound_np(i < n_cmds ? consolesuccesssound : consolefailsound);
1113 }
1114
1115 /********************> Tick() <*****/
1116 extern bool save_image(const char * fname);
1117 void Screenshot (void)
1118 {
1119         char temp[1024];
1120         time_t  t = time(NULL);
1121         struct  tm *tme = localtime(&t);
1122         sprintf(temp, "Screenshots/Screenshot_%04d_%02d_%02d--%02d_%02d_%02d.png", tme->tm_year + 1900, tme->tm_mon + 1, tme->tm_mday, tme->tm_hour, tme->tm_min, tme->tm_sec);
1123
1124         #if defined(_WIN32)
1125         mkdir("Screenshots");
1126         #else
1127         mkdir("Screenshots", S_IRWXU);
1128         #endif
1129         
1130         save_image(temp);
1131 }
1132
1133
1134
1135 void Game::SetUpLighting(){
1136         if(environment==snowyenvironment)
1137         light.setColors(.65,.65,.7,.4,.4,.44);
1138         if(environment==desertenvironment)
1139         light.setColors(.95,.95,.95,.4,.35,.3);
1140         if(environment==grassyenvironment)
1141         light.setColors(.95,.95,1,.4,.4,.44);
1142         if(!skyboxtexture)
1143         light.setColors(1,1,1,.4,.4,.4);
1144         float average;
1145         average=(skyboxlightr+skyboxlightg+skyboxlightb)/3;
1146         light.color[0]*=(skyboxlightr+average)/2;
1147         light.color[1]*=(skyboxlightg+average)/2;
1148         light.color[2]*=(skyboxlightb+average)/2;
1149         light.ambient[0]*=(skyboxlightr+average)/2;
1150         light.ambient[1]*=(skyboxlightg+average)/2;
1151         light.ambient[2]*=(skyboxlightb+average)/2;
1152 }
1153
1154 int Game::findPathDist(int start,int end){
1155         int smallestcount,count,connected;
1156         int last,last2,last3,last4;
1157         int closest;
1158
1159         smallestcount=1000;
1160         for(int i=0;i<50;i++){
1161                 count=0;
1162                 last=start;
1163                 last2=-1;
1164                 last3=-1;
1165                 last4=-1;
1166                 while(last!=end&&count<30){
1167                         closest=-1;
1168                         for(int j=0;j<numpathpoints;j++){
1169                                 if(j!=last&&j!=last2&&j!=last3&&j!=last4)
1170                                 {
1171                                         connected=0;
1172                                         if(numpathpointconnect[j])
1173                                                 for(int k=0;k<numpathpointconnect[j];k++){
1174                                                         if(pathpointconnect[j][k]==last)connected=1;
1175                                                 }
1176                     if(!connected)
1177                         if(numpathpointconnect[last])
1178                             for(int k=0;k<numpathpointconnect[last];k++){
1179                                 if(pathpointconnect[last][k]==j)connected=1;
1180                             }
1181                     if(connected)
1182                         if(closest==-1||Random()%2==0){
1183                             closest=j;
1184                         }
1185                                 }
1186                         }
1187                         last4=last3;
1188                         last3=last2;
1189                         last2=last;
1190                         last=closest;
1191                         count++;
1192                 }
1193                 if(count<smallestcount)smallestcount=count;
1194         }
1195         return smallestcount;
1196 }
1197
1198 int Game::checkcollide(XYZ startpoint,XYZ endpoint){
1199         static XYZ colpoint,colviewer,coltarget;
1200         static float minx,minz,maxx,maxz,miny,maxy;
1201
1202     minx=min(startpoint.x,endpoint.x)-1;
1203     miny=min(startpoint.y,endpoint.y)-1;
1204     minz=min(startpoint.z,endpoint.z)-1;
1205     maxx=max(startpoint.x,endpoint.x)+1;
1206     maxy=max(startpoint.y,endpoint.y)+1;
1207     maxz=max(startpoint.z,endpoint.z)+1;
1208
1209         for(int i=0;i<objects.numobjects;i++){
1210                 if(     objects.position[i].x>minx-objects.model[i].boundingsphereradius&&
1211                 objects.position[i].x<maxx+objects.model[i].boundingsphereradius&&
1212                 objects.position[i].y>miny-objects.model[i].boundingsphereradius&&
1213                 objects.position[i].y<maxy+objects.model[i].boundingsphereradius&&
1214                 objects.position[i].z>minz-objects.model[i].boundingsphereradius&&
1215                 objects.position[i].z<maxz+objects.model[i].boundingsphereradius){
1216                         if(     objects.type[i]!=treeleavestype&&
1217                     objects.type[i]!=bushtype&&
1218                     objects.type[i]!=firetype){
1219                                 colviewer=startpoint;
1220                                 coltarget=endpoint;
1221                                 if(objects.model[i].LineCheck(&colviewer,&coltarget,&colpoint,&objects.position[i],&objects.rotation[i])!=-1)return i;
1222                         }
1223                 }
1224         }
1225
1226         //if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)return 1000;
1227
1228         return -1;
1229 }
1230
1231 int Game::checkcollide(XYZ startpoint,XYZ endpoint,int what){
1232         static XYZ colpoint,colviewer,coltarget;
1233         static float minx,minz,maxx,maxz,miny,maxy;
1234         static int i; //FIXME: see below
1235
1236     minx=min(startpoint.x,endpoint.x)-1;
1237     miny=min(startpoint.y,endpoint.y)-1;
1238     minz=min(startpoint.z,endpoint.z)-1;
1239     maxx=max(startpoint.x,endpoint.x)+1;
1240     maxy=max(startpoint.y,endpoint.y)+1;
1241     maxz=max(startpoint.z,endpoint.z)+1;
1242
1243         if(what!=1000){
1244                 if(     objects.position[what].x>minx-objects.model[what].boundingsphereradius&&
1245                 objects.position[what].x<maxx+objects.model[what].boundingsphereradius&&
1246                 objects.position[what].y>miny-objects.model[what].boundingsphereradius&&
1247                 objects.position[what].y<maxy+objects.model[what].boundingsphereradius&&
1248                 objects.position[what].z>minz-objects.model[what].boundingsphereradius&&
1249                 objects.position[what].z<maxz+objects.model[what].boundingsphereradius){
1250                         if(     objects.type[what]!=treeleavestype&&
1251                     objects.type[what]!=bushtype&&
1252                     objects.type[what]!=firetype){
1253                                 colviewer=startpoint;
1254                                 coltarget=endpoint;
1255                 //FIXME: i/what
1256                                 if(objects.model[what].LineCheck(&colviewer,&coltarget,&colpoint,&objects.position[what],&objects.rotation[what])!=-1)return i;
1257                         }
1258                 }
1259         }
1260
1261         if(what==1000)if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)return 1000;
1262
1263         return -1;
1264 }
1265
1266 void    Game::Setenvironment(int which)
1267 {
1268         LOGFUNC;
1269
1270         LOG(" Setting environment...");
1271
1272         float temptexdetail;
1273         environment=which;
1274
1275         pause_sound(stream_music1snow);
1276         pause_sound(stream_music1grass);
1277         pause_sound(stream_music1desert);
1278         pause_sound(stream_wind);
1279         pause_sound(stream_desertambient);
1280
1281
1282         if(environment==snowyenvironment){
1283                 windvector=0;
1284                 windvector.z=3;
1285                 if(ambientsound)
1286                   emit_stream_np(stream_wind);
1287
1288                 LoadTexture(":Data:Textures:snowtree.png",&objects.treetextureptr,0,1);
1289                 LoadTexture(":Data:Textures:bushsnow.png",&objects.bushtextureptr,0,1);
1290                 LoadTexture(":Data:Textures:bouldersnow.jpg",&objects.rocktextureptr,1,0);
1291                 LoadTexture(":Data:Textures:snowbox.jpg",&objects.boxtextureptr,1,0);
1292
1293                 footstepsound = footstepsn1;
1294                 footstepsound2 = footstepsn2;
1295                 footstepsound3 = footstepst1;
1296                 footstepsound4 = footstepst2;
1297
1298                 LoadTexture(":Data:Textures:snow.jpg",&terraintexture,1,0);
1299
1300                 LoadTexture(":Data:Textures:rock.jpg",&terraintexture2,1,0);
1301
1302                 //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1303
1304
1305
1306
1307                 temptexdetail=texdetail;
1308                 if(texdetail>1)texdetail=4;
1309                 skybox.load(    ":Data:Textures:Skybox(snow):Front.jpg",
1310                         ":Data:Textures:Skybox(snow):Left.jpg",
1311                         ":Data:Textures:Skybox(snow):Back.jpg",
1312                         ":Data:Textures:Skybox(snow):Right.jpg",
1313                         ":Data:Textures:Skybox(snow):Up.jpg",
1314                         ":Data:Textures:Skybox(snow):Down.jpg");
1315
1316
1317
1318
1319                 texdetail=temptexdetail;
1320         }
1321         if(environment==desertenvironment){
1322                 windvector=0;
1323                 windvector.z=2;
1324                 LoadTexture(":Data:Textures:deserttree.png",&objects.treetextureptr,0,1);
1325                 LoadTexture(":Data:Textures:bushdesert.png",&objects.bushtextureptr,0,1);
1326                 LoadTexture(":Data:Textures:boulderdesert.jpg",&objects.rocktextureptr,1,0);
1327                 LoadTexture(":Data:Textures:desertbox.jpg",&objects.boxtextureptr,1,0);
1328
1329
1330                 if(ambientsound)
1331                   emit_stream_np(stream_desertambient);
1332
1333                 footstepsound = footstepsn1;
1334                 footstepsound2 = footstepsn2;
1335                 footstepsound3 = footstepsn1;
1336                 footstepsound4 = footstepsn2;
1337
1338                 LoadTexture(":Data:Textures:sand.jpg",&terraintexture,1,0);
1339
1340                 LoadTexture(":Data:Textures:sandslope.jpg",&terraintexture2,1,0);
1341
1342                 //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1343
1344
1345
1346                 temptexdetail=texdetail;
1347                 if(texdetail>1)texdetail=4;
1348                 skybox.load(    ":Data:Textures:Skybox(sand):Front.jpg",
1349                         ":Data:Textures:Skybox(sand):Left.jpg",
1350                         ":Data:Textures:Skybox(sand):Back.jpg",
1351                         ":Data:Textures:Skybox(sand):Right.jpg",
1352                         ":Data:Textures:Skybox(sand):Up.jpg",
1353                         ":Data:Textures:Skybox(sand):Down.jpg");
1354
1355
1356
1357
1358                 texdetail=temptexdetail;
1359         }
1360         if(environment==grassyenvironment){
1361                 windvector=0;
1362                 windvector.z=2;
1363                 LoadTexture(":Data:Textures:tree.png",&objects.treetextureptr,0,1);
1364                 LoadTexture(":Data:Textures:bush.png",&objects.bushtextureptr,0,1);
1365                 LoadTexture(":Data:Textures:boulder.jpg",&objects.rocktextureptr,1,0);
1366                 LoadTexture(":Data:Textures:grassbox.jpg",&objects.boxtextureptr,1,0);
1367
1368                 if(ambientsound)
1369                   emit_stream_np(stream_wind, 100.);
1370
1371                 footstepsound = footstepgr1;
1372                 footstepsound2 = footstepgr2;
1373                 footstepsound3 = footstepst1;
1374                 footstepsound4 = footstepst2;
1375
1376                 LoadTexture(":Data:Textures:grassdirt.jpg",&terraintexture,1,0);
1377
1378                 LoadTexture(":Data:Textures:mossrock.jpg",&terraintexture2,1,0);
1379
1380                 //LoadTexture(":Data:Textures:detail.png",&terraintexture3,1);
1381
1382
1383
1384                 temptexdetail=texdetail;
1385                 if(texdetail>1)texdetail=4;
1386                 skybox.load(    ":Data:Textures:Skybox(grass):Front.jpg",
1387                         ":Data:Textures:Skybox(grass):Left.jpg",
1388                         ":Data:Textures:Skybox(grass):Back.jpg",
1389                         ":Data:Textures:Skybox(grass):Right.jpg",
1390                         ":Data:Textures:Skybox(grass):Up.jpg",
1391                         ":Data:Textures:Skybox(grass):Down.jpg");
1392
1393
1394
1395                 texdetail=temptexdetail;
1396         }
1397         temptexdetail=texdetail;
1398         texdetail=1;
1399         terrain.load(":Data:Textures:heightmap.png");
1400
1401         texdetail=temptexdetail;
1402 }
1403
1404
1405 void    Game::Loadlevel(int which){
1406         stealthloading=0;
1407         whichlevel=which;
1408
1409         if (which == -1) {
1410             tutoriallevel = -1;
1411             Loadlevel("tutorial");
1412         } else if (which >= 0 && which <= 15) {
1413             char buf[32];
1414             snprintf(buf, 32, "map%d", which + 1);
1415             Loadlevel(buf);
1416         } else
1417             Loadlevel("mapsave");
1418 }
1419
1420 void    Game::Loadlevel(const char *name){
1421         static int oldlevel;
1422         int templength;
1423         float lamefloat;
1424         int lameint;
1425         static const char *pfx = ":Data:Maps:";
1426         char *buf;
1427
1428         float headprop,legprop,armprop,bodyprop;
1429
1430         LOGFUNC;
1431
1432         LOG(std::string("Loading level...") + name);
1433
1434         if(!gameon)visibleloading=1;
1435
1436         if(stealthloading)visibleloading=0;
1437
1438         if(!stillloading)loadtime=0;
1439         gamestarted=1;
1440
1441         numenvsounds=0;
1442         //visibleloading=1;
1443         if(tutoriallevel!=-1)tutoriallevel=0;
1444         else tutoriallevel=1;
1445
1446         if(tutoriallevel==1)tutorialstage=0;
1447         if(tutorialstage==0){
1448                 tutorialstagetime=0;
1449                 tutorialmaxtime=1;
1450         }
1451         loadingstuff=1;
1452         if(!firstload){
1453                 oldlevel=50;
1454         }
1455         pause_sound(whooshsound);
1456         pause_sound(stream_firesound);
1457
1458         // Change the map filename into something that is os specific
1459         buf = (char*) alloca(strlen(pfx) + strlen(name) + 1);
1460         sprintf(buf, "%s%s", pfx, name);
1461         const char *FixedFN = ConvertFileName(buf);
1462
1463         int mapvers;
1464         FILE                    *tfile;
1465         tfile=fopen( FixedFN, "rb" );
1466         if(tfile)
1467         {
1468                 pause_sound(stream_firesound);
1469
1470
1471                 scoreadded=0;
1472                 windialogue=0;
1473
1474                 hostiletime=0;
1475
1476                 won=0;
1477
1478                 //campaign=0;
1479                 animation[bounceidleanim].Load((char *)"Idle",middleheight,neutral);
1480
1481                 numdialogues=0;
1482
1483                 for(int i=0;i<20;i++)
1484                 {
1485                         dialoguegonethrough[i]=0;
1486                 }
1487
1488                 indialogue=-1;
1489                 cameramode=0;
1490
1491                 damagedealt=0;
1492                 damagetaken=0;
1493
1494                 if(accountactive)difficulty=accountactive->getDifficulty();
1495
1496                 if(difficulty!=2)minimap=1;
1497                 else minimap=0;
1498
1499                 numhotspots=0;
1500                 currenthotspot=-1;
1501                 bonustime=1;
1502
1503                 skyboxtexture=1;
1504                 skyboxr=1;
1505                 skyboxg=1;
1506                 skyboxb=1;
1507
1508                 freeze=0;
1509                 winfreeze=0;
1510
1511                 for(int i=0;i<100;i++)
1512                 {
1513                         bonusnum[i]=0;
1514                 }
1515
1516                 numfalls=0;
1517                 numflipfail=0;
1518                 numseen=0;
1519                 numstaffattack=0;
1520                 numswordattack=0;
1521                 numknifeattack=0;
1522                 numunarmedattack=0;
1523                 numescaped=0;
1524                 numflipped=0;
1525                 numwallflipped=0;
1526                 numthrowkill=0;
1527                 numafterkill=0;
1528                 numreversals=0;
1529                 numattacks=0;
1530                 maxalarmed=0;
1531                 numresponded=0;
1532
1533                 bonustotal=startbonustotal;
1534                 bonus=0;
1535                 gameon=1;
1536                 changedelay=0;
1537                 if(console)
1538                 {
1539                         emit_sound_np(consolesuccesssound);
1540                         freeze=0;
1541                         console=0;
1542                 }
1543
1544                 if(!stealthloading)
1545                 {
1546                         terrain.numdecals=0;
1547                         Sprite::deleteSprites();
1548                         for(int i=0;i<objects.numobjects;i++)
1549                         {
1550                                 objects.model[i].numdecals=0;
1551                         }
1552
1553                         int j=objects.numobjects;
1554                         for(int i=0;i<j;i++)
1555                         {
1556                                 objects.DeleteObject(0);
1557                                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1558                         }
1559
1560                         for(int i=0;i<subdivision;i++)
1561                         {
1562                                 for(int j=0;j<subdivision;j++)
1563                                 {
1564                                         terrain.patchobjectnum[i][j]=0;
1565                                 }
1566                         }
1567                         if(visibleloading){loadscreencolor=4; LoadingScreen();}
1568                 }
1569
1570                 weapons.numweapons=0;
1571
1572                 funpackf(tfile, "Bi", &mapvers);
1573                 if(mapvers>=15)funpackf(tfile, "Bi", &indemo);
1574                 else indemo=0;
1575                 if(mapvers>=5)funpackf(tfile, "Bi", &maptype);
1576                 else maptype=mapkilleveryone;
1577                 if(mapvers>=6)funpackf(tfile, "Bi", &hostile);
1578                 else hostile=1;
1579                 if(mapvers>=4)funpackf(tfile, "Bf Bf", &viewdistance, &fadestart);
1580                 else
1581                 {
1582                         viewdistance=100;
1583                         fadestart=.6;
1584                 }
1585                 if(mapvers>=2)funpackf(tfile, "Bb Bf Bf Bf", &skyboxtexture, &skyboxr, &skyboxg, &skyboxb);
1586                 else
1587                 {
1588                         skyboxtexture=1;
1589                         skyboxr=1;
1590                         skyboxg=1;
1591                         skyboxb=1;
1592                 }
1593                 if(mapvers>=10)funpackf(tfile, "Bf Bf Bf", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1594                 else
1595                 {
1596                         skyboxlightr=skyboxr;
1597                         skyboxlightg=skyboxg;
1598                         skyboxlightb=skyboxb;
1599                 }
1600                 if(!stealthloading)funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &player[0].coords.x,&player[0].coords.y,&player[0].coords.z,&player[0].rotation,&player[0].targetrotation, &player[0].num_weapons);
1601                 if(stealthloading)funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat,&lamefloat,&lamefloat,&lamefloat,&lamefloat, &player[0].num_weapons);
1602                 player[0].originalcoords=player[0].coords;
1603                 if(player[0].num_weapons>0&&player[0].num_weapons<5)
1604                 {
1605                         for(int j=0;j<player[0].num_weapons;j++)
1606                         {
1607                                 player[0].weaponids[j]=weapons.numweapons;
1608                                 funpackf(tfile, "Bi", &weapons.type[weapons.numweapons]);
1609                                 weapons.owner[weapons.numweapons]=0;
1610                                 weapons.numweapons++;
1611                         }
1612                 }
1613
1614                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1615
1616                 funpackf(tfile, "Bf Bf Bf", &player[0].armorhead, &player[0].armorhigh, &player[0].armorlow);
1617                 funpackf(tfile, "Bf Bf Bf", &player[0].protectionhead, &player[0].protectionhigh, &player[0].protectionlow);
1618                 funpackf(tfile, "Bf Bf Bf", &player[0].metalhead, &player[0].metalhigh, &player[0].metallow);
1619                 funpackf(tfile, "Bf Bf", &player[0].power, &player[0].speedmult);
1620
1621                 funpackf(tfile, "Bi", &player[0].numclothes);
1622
1623                 if(mapvers>=9)
1624                 {
1625                         funpackf(tfile, "Bi Bi", &player[0].whichskin, &player[0].creature);
1626                 }
1627                 else
1628                 {
1629                         player[0].whichskin=0;
1630                         player[0].creature=rabbittype;
1631                 }
1632
1633                 player[0].lastattack=-1;
1634                 player[0].lastattack2=-1;
1635                 player[0].lastattack3=-1;
1636
1637                 if(mapvers>=8)
1638                 {
1639                         funpackf(tfile, "Bi", &numdialogues);
1640                         if(numdialogues)
1641                         {
1642                                 for(int k=0;k<numdialogues;k++)
1643                                 {
1644                                         funpackf(tfile, "Bi", &numdialogueboxes[k]);
1645                                         funpackf(tfile, "Bi", &dialoguetype[k]);
1646                                         for(int l=0;l<10;l++)
1647                                         {
1648                                                 funpackf(tfile, "Bf Bf Bf", &participantlocation[k][l].x, &participantlocation[k][l].y, &participantlocation[k][l].z);
1649                                                 funpackf(tfile, "Bf", &participantrotation[k][l]);
1650                                         }
1651                                         if(numdialogueboxes)
1652                                         {
1653                                                 for(int l=0;l<numdialogueboxes[k];l++)
1654                                                 {
1655                                                         funpackf(tfile, "Bi", &dialogueboxlocation[k][l]);
1656                                                         funpackf(tfile, "Bf", &dialogueboxcolor[k][l][0]);
1657                                                         funpackf(tfile, "Bf", &dialogueboxcolor[k][l][1]);
1658                                                         funpackf(tfile, "Bf", &dialogueboxcolor[k][l][2]);
1659                                                         funpackf(tfile, "Bi", &dialogueboxsound[k][l]);
1660
1661                                                         bool doneread;
1662
1663                                                         funpackf(tfile, "Bi",&templength);
1664                                                         if(templength>128||templength<=0)templength=128;
1665                             int m;
1666                                                         for(m=0;m<templength;m++){
1667                                                                 funpackf(tfile, "Bb", &dialoguetext[k][l][m]);
1668                                                                 if(dialoguetext[k][l][m]=='\0')break;
1669                                                         }
1670                                                         dialoguetext[k][l][m] = 0;
1671
1672                                                         funpackf(tfile, "Bi",&templength);
1673                                                         if(templength>64||templength<=0)templength=64;
1674                                                         for(m=0;m<templength;m++){
1675                                                                 funpackf(tfile, "Bb", &dialoguename[k][l][m]);
1676                                                                 if(dialoguename[k][l][m]=='\0'){
1677                                                                         break;
1678                                                                 }
1679                                                         }
1680                                                         dialoguename[k][l][m] = 0;
1681                                                         funpackf(tfile, "Bf Bf Bf", &dialoguecamera[k][l].x, &dialoguecamera[k][l].y, &dialoguecamera[k][l].z);
1682                                                         funpackf(tfile, "Bi", &participantfocus[k][l]);
1683                                                         funpackf(tfile, "Bi", &participantaction[k][l]);
1684
1685                                                         for(m=0;m<10;m++)
1686                                                                 funpackf(tfile, "Bf Bf Bf", &participantfacing[k][l][m].x, &participantfacing[k][l][m].y, &participantfacing[k][l][m].z);
1687
1688                                                         funpackf(tfile, "Bf Bf",&dialoguecamerarotation[k][l],&dialoguecamerarotation2[k][l]);
1689                                                 }
1690                                         }
1691                                 }
1692                         }
1693                 }
1694                 else numdialogues=0;
1695
1696                 if(player[0].numclothes)
1697                 {
1698                         for(int k=0;k<player[0].numclothes;k++)
1699                         {
1700                                 funpackf(tfile, "Bi", &templength);
1701                                 for(int l=0;l<templength;l++)
1702                                         funpackf(tfile, "Bb", &player[0].clothes[k][l]);
1703                                 player[0].clothes[k][templength]='\0';
1704                                 funpackf(tfile, "Bf Bf Bf", &player[0].clothestintr[k], &player[0].clothestintg[k], &player[0].clothestintb[k]);
1705                         }
1706                 }
1707
1708                 funpackf(tfile, "Bi", &environment);
1709
1710                 funpackf(tfile, "Bi", &objects.numobjects);
1711                 if(objects.numobjects)
1712                 {
1713                         for(int i=0;i<objects.numobjects;i++)
1714                         {
1715                                 funpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", &objects.type[i],&objects.rotation[i],&objects.rotation2[i], &objects.position[i].x, &objects.position[i].y, &objects.position[i].z,&objects.scale[i]);
1716                                 if(objects.type[i]==treeleavestype)objects.scale[i]=objects.scale[i-1];
1717                         }
1718                 }
1719
1720                 if(mapvers>=7)
1721                 {
1722                         funpackf(tfile, "Bi", &numhotspots);
1723                         if(numhotspots)
1724                         {
1725                                 for(int i=0;i<numhotspots;i++)
1726                                 {
1727                                         funpackf(tfile, "Bi Bf Bf Bf Bf", &hotspottype[i],&hotspotsize[i],&hotspot[i].x,&hotspot[i].y,&hotspot[i].z);
1728                                         funpackf(tfile, "Bi", &templength);
1729                                         if(templength)
1730                                                 for(int l=0;l<templength;l++)
1731                                                         funpackf(tfile, "Bb", &hotspottext[i][l]);
1732                                         hotspottext[i][templength]='\0';
1733                                         if(hotspottype[i]==-111)indemo=1;
1734                                 }
1735                         }
1736                 }
1737                 else numhotspots=0;
1738
1739                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1740
1741                 if(!stealthloading)
1742                 {
1743                         objects.center=0;
1744                         for(int i=0;i<objects.numobjects;i++)
1745                         {
1746                                 objects.center+=objects.position[i];
1747                         }
1748                         objects.center/=objects.numobjects;
1749
1750
1751                         if(visibleloading){loadscreencolor=4; LoadingScreen();}
1752
1753                         float maxdistance=0;
1754                         float tempdist;
1755                         int whichclosest;
1756                         for(int i=0;i<objects.numobjects;i++)
1757                         {
1758                                 tempdist=findDistancefast(&objects.center,&objects.position[i]);
1759                                 if(tempdist>maxdistance)
1760                                 {
1761                                         whichclosest=i;
1762                                         maxdistance=tempdist;
1763                                 }
1764                         }
1765                         objects.radius=fast_sqrt(maxdistance);
1766                 }
1767
1768                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1769                 //mapcenter=objects.center;
1770                 //mapradius=objects.radius;
1771
1772                 funpackf(tfile, "Bi", &numplayers);
1773                 int howmanyremoved=0;
1774                 bool removeanother=0;
1775                 if(numplayers>1&&numplayers<maxplayers)
1776                 {
1777                         for(int i=1;i<numplayers;i++)
1778                         {
1779                                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1780                                 removeanother=0;
1781
1782                                 funpackf(tfile, "Bi Bi Bf Bf Bf Bi",&player[i-howmanyremoved].whichskin,&player[i-howmanyremoved].creature, &player[i-howmanyremoved].coords.x,&player[i-howmanyremoved].coords.y,&player[i-howmanyremoved].coords.z,&player[i-howmanyremoved].num_weapons);
1783                                 if(mapvers>=5)funpackf(tfile, "Bi", &player[i-howmanyremoved].howactive);
1784                                 else player[i-howmanyremoved].howactive=typeactive;
1785                                 if(mapvers>=3)funpackf(tfile, "Bf",&player[i-howmanyremoved].scale);
1786                                 else player[i-howmanyremoved].scale=-1;
1787                                 if(mapvers>=11)funpackf(tfile, "Bb",&player[i-howmanyremoved].immobile);
1788                                 else player[i-howmanyremoved].immobile=0;
1789                                 if(mapvers>=12)funpackf(tfile, "Bf",&player[i-howmanyremoved].rotation);
1790                                 else player[i-howmanyremoved].rotation=0;
1791                                 player[i-howmanyremoved].targetrotation=player[i-howmanyremoved].rotation;
1792                                 if(player[i-howmanyremoved].num_weapons<0||player[i-howmanyremoved].num_weapons>5){
1793                                         removeanother=1;
1794                                         howmanyremoved++;
1795                                 }
1796                                 if(!removeanother)
1797                                 {
1798                                         if(player[i-howmanyremoved].num_weapons>0&&player[i-howmanyremoved].num_weapons<5)
1799                                         {
1800                                                 for(int j=0;j<player[i-howmanyremoved].num_weapons;j++)
1801                                                 {
1802                                                         player[i-howmanyremoved].weaponids[j]=weapons.numweapons;
1803                                                         funpackf(tfile, "Bi", &weapons.type[player[i-howmanyremoved].weaponids[j]]);
1804                                                         weapons.owner[player[i-howmanyremoved].weaponids[j]]=i;
1805                                                         weapons.numweapons++;
1806                                                 }
1807                                         }
1808                                         funpackf(tfile, "Bi", &player[i-howmanyremoved].numwaypoints);
1809                                         //player[i-howmanyremoved].numwaypoints=10;
1810                                         for(int j=0;j<player[i-howmanyremoved].numwaypoints;j++)
1811                                         {
1812                                                 funpackf(tfile, "Bf", &player[i-howmanyremoved].waypoints[j].x);
1813                                                 funpackf(tfile, "Bf", &player[i-howmanyremoved].waypoints[j].y);
1814                                                 funpackf(tfile, "Bf", &player[i-howmanyremoved].waypoints[j].z);
1815                                                 if(mapvers>=5)funpackf(tfile, "Bi", &player[i-howmanyremoved].waypointtype[j]);
1816                                                 else player[i-howmanyremoved].waypointtype[j] = wpkeepwalking;
1817                                         }
1818
1819                                         funpackf(tfile, "Bi", &player[i-howmanyremoved].waypoint);
1820                                         if(player[i-howmanyremoved].waypoint>player[i-howmanyremoved].numwaypoints-1)player[i-howmanyremoved].waypoint=0;
1821
1822                                         funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].armorhead, &player[i-howmanyremoved].armorhigh, &player[i-howmanyremoved].armorlow);
1823                                         funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].protectionhead, &player[i-howmanyremoved].protectionhigh, &player[i-howmanyremoved].protectionlow);
1824                                         funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].metalhead, &player[i-howmanyremoved].metalhigh, &player[i-howmanyremoved].metallow);
1825                                         funpackf(tfile, "Bf Bf", &player[i-howmanyremoved].power, &player[i-howmanyremoved].speedmult);
1826
1827                                         if(mapvers>=4)funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
1828                                         else
1829                                         {
1830                                                 headprop=1;
1831                                                 bodyprop=1;
1832                                                 armprop=1;
1833                                                 legprop=1;
1834                                         }
1835                                         if(player[i-howmanyremoved].creature==wolftype)
1836                                         {
1837                                                 player[i-howmanyremoved].proportionhead=1.1*headprop;
1838                                                 player[i-howmanyremoved].proportionbody=1.1*bodyprop;
1839                                                 player[i-howmanyremoved].proportionarms=1.1*armprop;
1840                                                 player[i-howmanyremoved].proportionlegs=1.1*legprop;
1841                                         }
1842
1843                                         if(player[i-howmanyremoved].creature==rabbittype)
1844                                         {
1845                                                 player[i-howmanyremoved].proportionhead=1.2*headprop;
1846                                                 player[i-howmanyremoved].proportionbody=1.05*bodyprop;
1847                                                 player[i-howmanyremoved].proportionarms=1.00*armprop;
1848                                                 player[i-howmanyremoved].proportionlegs=1.1*legprop;
1849                                                 player[i-howmanyremoved].proportionlegs.y=1.05*legprop;
1850                                         }
1851
1852                                         funpackf(tfile, "Bi", &player[i-howmanyremoved].numclothes);
1853                                         if(player[i-howmanyremoved].numclothes)
1854                                         {
1855                                                 for(int k=0;k<player[i-howmanyremoved].numclothes;k++)
1856                                                 {
1857                                                         int templength;
1858                                                         funpackf(tfile, "Bi", &templength);
1859                                                         for(int l=0;l<templength;l++)
1860                                                                 funpackf(tfile, "Bb", &player[i-howmanyremoved].clothes[k][l]);
1861                                                         player[i-howmanyremoved].clothes[k][templength]='\0';
1862                                                         funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].clothestintr[k], &player[i-howmanyremoved].clothestintg[k], &player[i-howmanyremoved].clothestintb[k]);
1863                                                 }
1864                                         }
1865                                 }
1866                         }
1867                 }
1868                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1869
1870                 numplayers-=howmanyremoved;
1871                 funpackf(tfile, "Bi", &numpathpoints);
1872                 if(numpathpoints>30||numpathpoints<0)
1873                         numpathpoints=0;
1874                 if(numpathpoints)
1875                 {
1876                         for(int j=0;j<numpathpoints;j++)
1877                         {
1878                                 funpackf(tfile, "Bf Bf Bf Bi", &pathpoint[j].x,&pathpoint[j].y,&pathpoint[j].z,&numpathpointconnect[j]);
1879                                 for(int k=0;k<numpathpointconnect[j];k++){
1880                                         funpackf(tfile, "Bi", &pathpointconnect[j][k]);
1881                                 }
1882                         }
1883                 }
1884                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1885
1886                 funpackf(tfile, "Bf Bf Bf Bf", &mapcenter.x,&mapcenter.y,&mapcenter.z,&mapradius);
1887
1888                 SetUpLighting();
1889                 if(environment!=oldenvironment)
1890             Setenvironment(environment);
1891                 oldenvironment=environment;
1892
1893                 if(!stealthloading)
1894                 {
1895                         int j=objects.numobjects;
1896                         objects.numobjects=0;
1897                         for(int i=0;i<j;i++)
1898                         {
1899                                 //if(objects.type[i]!=spiketype)
1900                                 objects.MakeObject(objects.type[i],objects.position[i],objects.rotation[i],objects.rotation2[i],objects.scale[i]);
1901                                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
1902                         }
1903
1904                         //if(skyboxtexture){
1905                         terrain.DoShadows();
1906                         if(visibleloading){loadscreencolor=4; LoadingScreen();}
1907                         objects.DoShadows();
1908                         if(visibleloading){loadscreencolor=4; LoadingScreen();}
1909                         /*}
1910                         else terrain.DoLighting();
1911                         */
1912                 }
1913
1914                 fclose(tfile);
1915
1916                 oldlevel=whichlevel;
1917
1918
1919                 if(numplayers>maxplayers-1)numplayers=maxplayers-1;
1920                 for(int i=0;i<numplayers;i++)
1921                 {
1922                         if(visibleloading){loadscreencolor=4; LoadingScreen();}
1923                         player[i].burnt=0;
1924                         player[i].bled=0;
1925                         player[i].onfire=0;
1926                         if(i==0||player[i].scale<0)player[i].scale=.2;
1927                         player[i].skeleton.free=0;
1928                         player[i].skeleton.id=i;
1929                         //if(Random()%2==0)player[i].creature=wolftype;
1930                         //else player[i].creature=rabbittype;
1931                         if(i==0&&mapvers<9)player[i].creature=rabbittype;
1932                         if(player[i].creature!=wolftype)player[i].skeleton.Load(
1933                     (char *)":Data:Skeleton:Basic Figure",
1934                     (char *)":Data:Skeleton:Basic Figurelow",
1935                     (char *)":Data:Skeleton:Rabbitbelt",
1936                     (char *)":Data:Models:Body.solid",
1937                     (char *)":Data:Models:Body2.solid",
1938                     (char *)":Data:Models:Body3.solid",
1939                     (char *)":Data:Models:Body4.solid",
1940                     (char *)":Data:Models:Body5.solid",
1941                     (char *)":Data:Models:Body6.solid",
1942                     (char *)":Data:Models:Body7.solid",
1943                     (char *)":Data:Models:Bodylow.solid",
1944                     (char *)":Data:Models:Belt.solid",0);
1945                         else
1946                         {
1947                                 if(player[i].creature!=wolftype){
1948                                         player[i].skeleton.Load(
1949                             (char *)":Data:Skeleton:Basic Figure",
1950                             (char *)":Data:Skeleton:Basic Figurelow",
1951                             (char *)":Data:Skeleton:Rabbitbelt",
1952                             (char *)":Data:Models:Body.solid",
1953                             (char *)":Data:Models:Body2.solid",
1954                             (char *)":Data:Models:Body3.solid",
1955                             (char *)":Data:Models:Body4.solid",
1956                             (char *)":Data:Models:Body5.solid",
1957                             (char *)":Data:Models:Body6.solid",
1958                             (char *)":Data:Models:Body7.solid",
1959                             (char *)":Data:Models:Bodylow.solid",
1960                             (char *)":Data:Models:Belt.solid",1);
1961                                         LoadTexture(":Data:Textures:Belt.png",&player[i].skeleton.drawmodelclothes.textureptr,1,1);
1962                                 }
1963                                 if(player[i].creature==wolftype){
1964                                         player[i].skeleton.Load(
1965                             (char *)":Data:Skeleton:Basic Figure Wolf",
1966                             (char *)":Data:Skeleton:Basic Figure Wolf Low",
1967                             (char *)":Data:Skeleton:Rabbitbelt",
1968                             (char *)":Data:Models:Wolf.solid",
1969                             (char *)":Data:Models:Wolf2.solid",
1970                             (char *)":Data:Models:Wolf3.solid",
1971                             (char *)":Data:Models:Wolf4.solid",
1972                             (char *)":Data:Models:Wolf5.solid",
1973                             (char *)":Data:Models:Wolf6.solid",
1974                             (char *)":Data:Models:Wolf7.solid",
1975                             (char *)":Data:Models:Wolflow.solid",
1976                             (char *)":Data:Models:Belt.solid",0);
1977                                 }
1978                         }
1979
1980
1981                         int texsize;
1982                         texsize=512*512*3/texdetail/texdetail;
1983                         //if(!player[i].loaded)player[i].skeleton.skinText = new GLubyte[texsize];
1984                         //player[i].skeleton.skinText.resize(texsize);
1985
1986                         LoadTextureSave(creatureskin[player[i].creature][player[i].whichskin],&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
1987
1988                         if(player[i].numclothes)
1989                         {
1990                                 for(int j=0;j<player[i].numclothes;j++)
1991                                 {
1992                                         tintr=player[i].clothestintr[j];
1993                                         tintg=player[i].clothestintg[j];
1994                                         tintb=player[i].clothestintb[j];
1995                                         AddClothes((char *)player[i].clothes[j],0,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
1996                                 }
1997                                 player[i].DoMipmaps();
1998                         }
1999
2000                         player[i].currentanimation=bounceidleanim;
2001                         player[i].targetanimation=bounceidleanim;
2002                         player[i].currentframe=0;
2003                         player[i].targetframe=1;
2004                         player[i].target=0;
2005                         player[i].speed=1+(float)(Random()%100)/1000;
2006                         if(difficulty==0)player[i].speed-=.2;
2007                         if(difficulty==1)player[i].speed-=.1;
2008
2009                         player[i].velocity=0;
2010                         player[i].oldcoords=player[i].coords;
2011                         player[i].realoldcoords=player[i].coords;
2012
2013                         player[i].id=i;
2014                         player[i].skeleton.id=i;
2015                         player[i].updatedelay=0;
2016                         player[i].normalsupdatedelay=0;
2017
2018                         player[i].aitype=passivetype;
2019                         player[i].madskills=0;
2020
2021                         if(i==0)
2022                         {
2023                                 player[i].proportionhead=1.2;
2024                                 player[i].proportionbody=1.05;
2025                                 player[i].proportionarms=1.00;
2026                                 player[i].proportionlegs=1.1;
2027                                 player[i].proportionlegs.y=1.05;
2028                         }
2029                         player[i].headless=0;
2030                         player[i].currentoffset=0;
2031                         player[i].targetoffset=0;
2032                         /*player[i].armorhead=1;
2033                         player[i].armorhigh=1;
2034                         player[i].armorlow=1;
2035                         player[i].protectionhead=1;
2036                         player[i].protectionhigh=1;
2037                         player[i].protectionlow=1;
2038                         player[i].metalhead=1;
2039                         player[i].metalhigh=1;
2040                         player[i].metallow=1;
2041                         player[i].power=1;
2042                         player[i].speedmult=1;*/
2043
2044                         player[i].damagetolerance=200;
2045
2046                         if(player[i].creature==wolftype)
2047                         {
2048                                 /*player[i].proportionhead=1.1;
2049                                 player[i].proportionbody=1.1;
2050                                 player[i].proportionarms=1.1;
2051                                 player[i].proportionlegs=1.1;
2052                                 player[i].proportionlegs.y=1.1;*/
2053                                 if(i==0||player[i].scale<0)player[i].scale=.23;
2054
2055                                 player[i].damagetolerance=300;
2056                         }
2057
2058                         if(visibleloading){loadscreencolor=4; LoadingScreen();}
2059                         if(cellophane)
2060                         {
2061                                 player[i].proportionhead.z=0;
2062                                 player[i].proportionbody.z=0;
2063                                 player[i].proportionarms.z=0;
2064                                 player[i].proportionlegs.z=0;
2065                         }
2066
2067                         player[i].tempanimation.Load((char *)"Tempanim",0,0);
2068
2069                         player[i].headmorphness=0;
2070                         player[i].targetheadmorphness=1;
2071                         player[i].headmorphstart=0;
2072                         player[i].headmorphend=0;
2073
2074                         player[i].pausetime=0;
2075
2076                         player[i].dead=0;
2077                         player[i].jumppower=5;
2078                         player[i].damage=0;
2079                         player[i].permanentdamage=0;
2080                         player[i].superpermanentdamage=0;
2081
2082                         player[i].forwardkeydown=0;
2083                         player[i].leftkeydown=0;
2084                         player[i].backkeydown=0;
2085                         player[i].rightkeydown=0;
2086                         player[i].jumpkeydown=0;
2087                         player[i].crouchkeydown=0;
2088                         player[i].throwkeydown=0;
2089
2090                         player[i].collided=-10;
2091                         player[i].loaded=1;
2092                         player[i].bloodloss=0;
2093                         player[i].weaponactive=-1;
2094                         player[i].weaponstuck=-1;
2095                         player[i].bleeding=0;
2096                         player[i].deathbleeding=0;
2097                         player[i].stunned=0;
2098                         player[i].hasvictim=0;
2099                         player[i].wentforweapon=0;
2100                 }
2101
2102                 player[0].aitype=playercontrolled;
2103                 player[0].weaponactive=-1;
2104
2105                 if(difficulty==1)
2106                 {
2107                         //player[0].speedmult=1/.9;
2108                         player[0].power=1/.9;
2109                 }
2110
2111                 if(difficulty==0)
2112                 {
2113                         //player[0].speedmult=1/.8;
2114                         player[0].power=1/.8;
2115                 }
2116
2117                 //player[0].weaponstuck=1;
2118
2119                 if(difficulty==1)player[0].damagetolerance=250;
2120                 if(difficulty==0)player[0].damagetolerance=300;
2121                 if(difficulty==0)player[0].armorhead*=1.5;
2122                 if(difficulty==0)player[0].armorhigh*=1.5;
2123                 if(difficulty==0)player[0].armorlow*=1.5;
2124                 cameraloc=player[0].coords;
2125                 cameraloc.y+=5;
2126                 rotation=player[0].rotation;
2127
2128                 hawkcoords=player[0].coords;
2129                 hawkcoords.y+=30;
2130
2131                 if(visibleloading){loadscreencolor=4; LoadingScreen();}
2132                 //weapons.numweapons=numplayers;
2133                 for(int i=0;i<weapons.numweapons;i++)
2134                 {
2135                         weapons.bloody[i]=0;
2136                         weapons.blooddrip[i]=0;
2137                         weapons.blooddripdelay[i]=0;
2138                         weapons.onfire[i]=0;
2139                         weapons.flamedelay[i]=0;
2140                         weapons.damage[i]=0;
2141                         //weapons.type[i]=sword;
2142                         if(weapons.type[i]==sword){
2143                                 weapons.mass[i]=1.5;
2144                                 weapons.tipmass[i]=1;
2145                                 weapons.length[i]=.8;
2146                         }
2147                         if(weapons.type[i]==staff){
2148                                 weapons.mass[i]=2;
2149                                 weapons.tipmass[i]=1;
2150                                 weapons.length[i]=1.5;
2151                         }
2152                         if(weapons.type[i]==knife){
2153                                 weapons.mass[i]=1;
2154                                 weapons.tipmass[i]=1.2;
2155                                 weapons.length[i]=.25;
2156                         }
2157                         weapons.position[i]=-1000;
2158                         weapons.tippoint[i]=-1000;
2159                 }
2160                 
2161                 LOG("Starting background music...");
2162
2163                 OPENAL_StopSound(OPENAL_ALL);
2164                 if(environment==snowyenvironment)
2165                 {
2166                         if(ambientsound)
2167                           emit_stream_np(stream_wind);
2168                 }
2169                 else if(environment==desertenvironment)
2170                 {
2171                         if(ambientsound)
2172                           emit_stream_np(stream_desertambient);
2173                 }
2174                 else if(environment==grassyenvironment)
2175                 {
2176                         if(ambientsound)
2177                           emit_stream_np(stream_wind, 100.);
2178                 }
2179                 oldmusicvolume[0]=0;
2180                 oldmusicvolume[1]=0;
2181                 oldmusicvolume[2]=0;
2182                 oldmusicvolume[3]=0;
2183
2184                 if(!firstload)
2185                 {
2186                         firstload=1;
2187                 }
2188         }
2189         leveltime=0;
2190         loadingstuff=0;
2191         visibleloading=0;
2192 }
2193
2194
2195
2196 void Game::MenuTick(){
2197     //menu buttons
2198     if(mainmenu==1||mainmenu==2){
2199         if(Input::MouseClicked()&&selected==1){
2200             if(!gameon){
2201                 fireSound(firestartsound);
2202                 flash();
2203                 //new game
2204                 if(accountactive) {
2205                     mainmenu=5;
2206                 } else {
2207                     mainmenu=7;
2208                 }
2209                 selected=-1;
2210             }else{
2211                 //resume
2212                 mainmenu=0;
2213                 pause_sound(stream_music3);
2214                 resume_stream(music1);
2215             }
2216         }
2217
2218         if(Input::MouseClicked()&&selected==2){
2219             fireSound();
2220             flash();
2221             //options
2222             mainmenu=3;
2223             if(newdetail>2)newdetail=detail;
2224             if(newdetail<0)newdetail=detail;
2225             if(newscreenwidth>3000)newscreenwidth=screenwidth;
2226             if(newscreenwidth<0)newscreenwidth=screenwidth;
2227             if(newscreenheight>3000)newscreenheight=screenheight;
2228             if(newscreenheight<0)newscreenheight=screenheight;
2229         }
2230
2231         if(Input::MouseClicked()&&selected==3){
2232             fireSound();
2233             flash();
2234             if(!gameon){
2235                 //quit
2236                 tryquit=1;
2237                 pause_sound(stream_music3);
2238             }else{
2239                 //end game
2240                 gameon=0;
2241                 mainmenu=1;
2242             }
2243         }
2244     }
2245     if(mainmenu==3){
2246         if(Input::MouseClicked()){
2247
2248             if(selected!=-1)
2249                 fireSound();
2250
2251             switch(selected){
2252                 case 0: {
2253                     extern SDL_Rect **resolutions;
2254                     bool isCustomResolution = true;
2255                     bool found = false;
2256                     for(int i = 0; (!found) && (resolutions[i]); i++){
2257                         if((resolutions[i]->w == screenwidth) && (resolutions[i]->h == screenwidth))
2258                             isCustomResolution = false;
2259
2260                         if((resolutions[i]->w == newscreenwidth) && (resolutions[i]->h == newscreenheight)){
2261                             i++;
2262                             if(resolutions[i] != NULL){
2263                                 newscreenwidth = (int) resolutions[i]->w;
2264                                 newscreenheight = (int) resolutions[i]->h;
2265                             }else if(isCustomResolution){
2266                                 if((screenwidth == newscreenwidth) && (screenheight == newscreenheight)){
2267                                     newscreenwidth = (int) resolutions[0]->w;
2268                                     newscreenheight = (int) resolutions[0]->h;
2269                                 }else{
2270                                     newscreenwidth = screenwidth;
2271                                     newscreenheight = screenheight;
2272                                 }
2273                             }else{
2274                                 newscreenwidth = (int) resolutions[0]->w;
2275                                 newscreenheight = (int) resolutions[0]->h;
2276                             }
2277                             found = true;
2278                         }
2279                     }
2280
2281                     if(!found){
2282                         newscreenwidth = (int) resolutions[0]->w;
2283                         newscreenheight = (int) resolutions[0]->h;
2284                     }
2285                     } break;
2286                 case 1:
2287                     newdetail++;
2288                     if(newdetail>2)newdetail=0;
2289                     break;
2290                 case 2:
2291                     bloodtoggle++;
2292                     if(bloodtoggle>2)bloodtoggle=0;
2293                     break;
2294                 case 3:
2295                     difficulty++;
2296                     if(difficulty>2)difficulty=0;
2297                     break;
2298                 case 4:
2299                     ismotionblur=1-ismotionblur;
2300                     break;
2301                 case 5:
2302                     decals=1-decals;
2303                     break;
2304                 case 6:
2305                     musictoggle=1-musictoggle;
2306
2307                     if(!musictoggle){
2308                         pause_sound(music1);
2309                         pause_sound(stream_music2);
2310                         pause_sound(stream_music3);
2311
2312                         for(int i=0;i<4;i++){
2313                             oldmusicvolume[i]=0;
2314                             musicvolume[i]=0;
2315                         }
2316                     }
2317
2318                     if(musictoggle)
2319                       emit_stream_np(stream_music3);
2320                     break;
2321                 case 7:
2322                     flash();
2323                     //options
2324                     mainmenu=4;
2325                     selected=-1;
2326                     keyselect=-1;
2327                     break;
2328                 case 8:
2329                     flash();
2330
2331                     if(newdetail>2)newdetail=detail;
2332                     if(newdetail<0)newdetail=detail;
2333                     if(newscreenwidth<0)newscreenwidth=screenwidth;
2334                     if(newscreenheight<0)newscreenheight=screenheight;
2335
2336                     SaveSettings(*this);
2337                     if(mainmenu==3&&gameon)mainmenu=2;
2338                     if(mainmenu==3&&!gameon)mainmenu=1;
2339                     break;
2340                 case 9:
2341                     invertmouse=1-invertmouse;
2342                     break;
2343                 case 10:
2344                     usermousesensitivity+=.2;
2345                     if(usermousesensitivity>2)usermousesensitivity=.2;
2346                     break;
2347                 case 11:
2348                     volume+=.1f;
2349                     if(volume>1.0001f)volume=0;
2350                     OPENAL_SetSFXMasterVolume((int)(volume*255));
2351                     break;
2352                 case 12:
2353                     flash();
2354                     
2355                     newstereomode = stereomode;
2356                     mainmenu=18;
2357                     keyselect=-1;
2358                     break;
2359                 case 13:
2360                     showdamagebar=!showdamagebar;
2361                     break;
2362             }
2363         }
2364     }
2365     if(mainmenu==4){
2366         if(Input::MouseClicked()&&selected!=-1&&!waiting){
2367             fireSound();
2368             if(selected<9&&keyselect==-1)
2369                 keyselect=selected;
2370             if(keyselect!=-1)
2371                 setKeySelected();
2372             if(selected==9){
2373                 flash();
2374
2375                 mainmenu=3;
2376
2377                 if(newdetail>2)newdetail=detail;
2378                 if(newdetail<0)newdetail=detail;
2379                 if(newscreenwidth>3000)newscreenwidth=screenwidth;
2380                 if(newscreenwidth<0)newscreenwidth=screenwidth;
2381                 if(newscreenheight>3000)newscreenheight=screenheight;
2382                 if(newscreenheight<0)newscreenheight=screenheight;
2383             }
2384         }
2385     }
2386
2387     if(mainmenu==5){
2388
2389         if(endgame==2){
2390             accountactive->endGame();
2391             endgame=0;
2392         }
2393
2394         if(Input::MouseClicked()){
2395             if((selected-7>=accountactive->getCampaignChoicesMade())){
2396                 fireSound();
2397                 flash();
2398                 startbonustotal=0;
2399
2400                 loading=2;
2401                 loadtime=0;
2402                 targetlevel=7;
2403                 if(firstload) TickOnceAfter();
2404                 else LoadStuff();
2405                 whichchoice=selected-7-accountactive->getCampaignChoicesMade();
2406                 visibleloading=1;
2407                 stillloading=1;
2408                 Loadlevel(campaignmapname[campaignchoicewhich[selected-7-accountactive->getCampaignChoicesMade()]]);
2409                 //Loadlevel(campaignmapname[levelorder[selected-7]]);
2410                 campaign=1;
2411                 mainmenu=0;
2412                 gameon=1;
2413                 pause_sound(stream_music3);
2414             }
2415             if(selected>=1 && selected<=5){
2416                 fireSound();
2417                 flash();
2418             }
2419             switch(selected){
2420                 case 1:
2421                     startbonustotal=0;
2422
2423                     loading=2;
2424                     loadtime=0;
2425                     targetlevel=-1;
2426                     if(firstload)TickOnceAfter();
2427                     if(!firstload)LoadStuff();
2428                     else {
2429                         Loadlevel(-1);
2430                     }
2431
2432                     mainmenu=0;
2433                     gameon=1;
2434                     pause_sound(stream_music3);
2435                     break;
2436                 case 2:
2437                     mainmenu=9;
2438                     break;
2439                 case 3:
2440                     mainmenu=6;
2441                     break;
2442                 case 4:
2443                     if(mainmenu==5&&gameon)mainmenu=2;
2444                     if(mainmenu==5&&!gameon)mainmenu=1;
2445                     break;
2446                 case 5:
2447                     mainmenu=7;
2448                     break;
2449             }
2450         }
2451     }
2452     else if(mainmenu==9){
2453         if(Input::MouseClicked()&&selected<numchallengelevels&&selected>=0&&selected<=accountactive->getProgress()){
2454             fireSound();
2455             flash();
2456
2457             startbonustotal=0;
2458
2459             loading=2;
2460             loadtime=0;
2461             targetlevel=selected;
2462             if(firstload)TickOnceAfter();
2463             if(!firstload)LoadStuff();
2464             else {
2465                 Loadlevel(selected);
2466             }
2467             campaign=0;
2468
2469             mainmenu=0;
2470             gameon=1;
2471             pause_sound(stream_music3);
2472         }
2473         if(Input::MouseClicked()&&selected==numchallengelevels){
2474             fireSound();
2475             flash();
2476             mainmenu=5;
2477         }
2478     }
2479     if(mainmenu==10){
2480         endgame=2;
2481         if(Input::MouseClicked()&&selected==3){
2482             fireSound();
2483             flash();
2484             mainmenu=5;
2485         }
2486     }
2487
2488     if(mainmenu==6){
2489         if(Input::MouseClicked()) {
2490             if(selected>-1){
2491                 fireSound();
2492                 if(selected==1) {
2493                     flash();
2494                     accountactive = Account::destroy(accountactive);
2495                     mainmenu=7;
2496                 } else if(selected==2) {
2497                     flash();
2498                     mainmenu=5;
2499                 }
2500             }
2501         }
2502     }
2503     if(mainmenu==7){
2504         if(Input::MouseClicked()) {
2505             if(selected!=-1){
2506                 fireSound();
2507                 if(selected==0&&Account::getNbAccounts()<8){
2508                     entername=1;
2509                 } else if (selected<Account::getNbAccounts()+1) {
2510                     accountactive=Account::get(selected-1);
2511                     mainmenu=5;
2512                     flash();
2513                 } else if (selected==Account::getNbAccounts()+1) {
2514                     flash();
2515
2516                     mainmenu=1;
2517
2518                     for(int j=0;j<255;j++){
2519                         displaytext[0][j]=' ';
2520                     }
2521                     displaychars[0]=0;
2522                     displayselected=0;
2523                     entername=0;
2524                 }
2525             }
2526         }
2527     }
2528     if(mainmenu==8){
2529         if(Input::MouseClicked()&&selected>-1){
2530             fireSound();
2531             flash();
2532             if(selected<=2)
2533                 accountactive->setDifficulty(selected);
2534             mainmenu=5;
2535         }
2536     }
2537     if (mainmenu==18) {                 
2538         if(Input::MouseClicked()&&selected==0) {
2539             newstereomode = (StereoMode)(newstereomode + 1);
2540             while(!CanInitStereo(newstereomode)) {
2541                 printf("Failed to initialize mode %s (%i)\n", StereoModeName(newstereomode), newstereomode);
2542                 newstereomode = (StereoMode)(newstereomode + 1);
2543                 if ( newstereomode >= stereoCount ) {
2544                     newstereomode = stereoNone;
2545                 }
2546             }
2547         }
2548         
2549         if(Input::isKeyPressed(MOUSEBUTTON1)&&selected==1)
2550             stereoseparation+=0.001;
2551         if(Input::isKeyPressed(MOUSEBUTTON2)&&selected==1)
2552             stereoseparation-=0.001;
2553
2554         if(Input::MouseClicked()&&selected==2) {
2555             stereoreverse =! stereoreverse;
2556         }
2557         
2558         if(Input::MouseClicked()&&selected==3) {
2559             flash();
2560
2561             stereomode = newstereomode;
2562             InitStereo(stereomode);
2563             
2564             mainmenu=3;
2565         }
2566     }
2567
2568     if(Input::isKeyDown(SDLK_q)&&Input::isKeyDown(SDLK_LMETA)){
2569         tryquit=1;
2570         if(mainmenu==3){
2571             if(newdetail>2)newdetail=detail;
2572             if(newdetail<0)newdetail=detail;
2573             if(newscreenwidth<0)newscreenwidth=screenwidth;
2574             if(newscreenheight<0)newscreenheight=screenheight;
2575
2576             SaveSettings(*this);
2577         }
2578     }
2579
2580     if(mainmenu==1||mainmenu==2){
2581         if(loaddistrib>4)transition+=multiplier/8;
2582         if(transition>1){
2583             transition=0;
2584             anim++;
2585             if(anim>4)anim=0;
2586             loaddistrib=0;
2587         }
2588     }
2589     OPENAL_SetFrequency(channels[stream_music3], 22050);
2590
2591     if(entername) {
2592         inputText(displaytext[0],&displayselected,&displaychars[0]);
2593         if(!waiting) { // the input as finished
2594             if(displaychars[0]){ // with enter
2595                 accountactive = Account::add(string(displaytext[0]));
2596
2597                 mainmenu=8;
2598
2599                 flash();
2600
2601                 fireSound(firestartsound);
2602
2603                 for(int i=0;i<255;i++){
2604                     displaytext[0][i]=' ';
2605                 }
2606                 displaychars[0]=0;
2607
2608                 displayselected=0;
2609             }
2610             entername=0;
2611         }
2612         
2613         displayblinkdelay-=multiplier;
2614         if(displayblinkdelay<=0){
2615             displayblinkdelay=.3;
2616             displayblink=1-displayblink;
2617         }
2618     }
2619 }
2620
2621 void Game::doTutorial(){
2622     if(tutorialstagetime>tutorialmaxtime){
2623         tutorialstage++;
2624         tutorialsuccess=0;
2625         if(tutorialstage<=1){
2626             canattack=0;
2627             cananger=0;
2628             reversaltrain=0;
2629         }
2630         switch(tutorialstage){
2631             case 1:
2632                 tutorialmaxtime=5;
2633             break; case 2:
2634                 tutorialmaxtime=2;
2635             break; case 3:
2636                 tutorialmaxtime=600;
2637             break; case 4:
2638                 tutorialmaxtime=1000;
2639             break; case 5:
2640                 tutorialmaxtime=600;
2641             break; case 6:
2642                 tutorialmaxtime=600;
2643             break; case 7:
2644                 tutorialmaxtime=600;
2645             break; case 8:
2646                 tutorialmaxtime=600;
2647             break; case 9:
2648                 tutorialmaxtime=600;
2649             break; case 10:
2650                 tutorialmaxtime=2;
2651             break; case 11:
2652                 tutorialmaxtime=1000;
2653             break; case 12:
2654                 tutorialmaxtime=1000;
2655             break; case 13:
2656                 tutorialmaxtime=2;
2657             break; case 14: {
2658                 tutorialmaxtime=3;
2659
2660                 XYZ temp,temp2;
2661
2662                 temp.x=1011;
2663                 temp.y=84;
2664                 temp.z=491;
2665                 temp2.x=1025;
2666                 temp2.y=75;
2667                 temp2.z=447;
2668
2669                 player[1].coords=(temp+temp2)/2;
2670
2671                 emit_sound_at(fireendsound, player[1].coords);
2672
2673                 for(int i=0;i<player[1].skeleton.num_joints;i++){
2674                     if(Random()%2==0){
2675                         if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
2676                         if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
2677                         if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
2678                         if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
2679                         Sprite::MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
2680                     }
2681                 }
2682             }
2683             break; case 15:
2684                 tutorialmaxtime=500;
2685             break; case 16:
2686                 tutorialmaxtime=500;
2687             break; case 17:
2688                 tutorialmaxtime=500;
2689             break; case 18:
2690                 tutorialmaxtime=500;
2691             break; case 19:
2692                 tutorialstage=20;
2693                 //tutorialmaxtime=500;
2694             break; case 20:
2695                 tutorialmaxtime=500;
2696             break; case 21:
2697                 tutorialmaxtime=500;
2698                 if(bonus==cannon){
2699                     bonus=Slicebonus;
2700                     againbonus=1;
2701                 }
2702                 else againbonus=0;
2703             break; case 22:
2704                 tutorialmaxtime=500;
2705             break; case 23:
2706                 tutorialmaxtime=500;
2707             break; case 24:
2708                 tutorialmaxtime=500;
2709             break; case 25:
2710                 tutorialmaxtime=500;
2711             break; case 26:
2712                 tutorialmaxtime=2;
2713             break; case 27:
2714                 tutorialmaxtime=4;
2715                 reversaltrain=1;
2716                 cananger=1;
2717                 player[1].aitype=attacktypecutoff;
2718             break; case 28:
2719                 tutorialmaxtime=400;
2720             break; case 29:
2721                 tutorialmaxtime=400;
2722                 player[0].escapednum=0;
2723             break; case 30:
2724                 tutorialmaxtime=4;
2725                 reversaltrain=0;
2726                 cananger=0;
2727                 player[1].aitype=passivetype;
2728             break; case 31:
2729                 tutorialmaxtime=13;
2730             break; case 32:
2731                 tutorialmaxtime=8;
2732             break; case 33:
2733                 tutorialmaxtime=400;
2734                 cananger=1;
2735                 canattack=1;
2736                 player[1].aitype=attacktypecutoff;
2737             break; case 34:
2738                 tutorialmaxtime=400;
2739             break; case 35:
2740                 tutorialmaxtime=400;
2741             break; case 36:
2742                 tutorialmaxtime=2;
2743                 reversaltrain=0;
2744                 cananger=0;
2745                 player[1].aitype=passivetype;
2746             break; case 37:
2747                 damagedealt=0;
2748                 damagetaken=0;
2749                 tutorialmaxtime=50;
2750                 cananger=1;
2751                 canattack=1;
2752                 player[1].aitype=attacktypecutoff;
2753             break; case 38:
2754                 tutorialmaxtime=4;
2755                 canattack=0;
2756                 cananger=0;
2757                 player[1].aitype=passivetype;
2758             break; case 39: {
2759                 XYZ temp,temp2;
2760
2761                 temp.x=1011;
2762                 temp.y=84;
2763                 temp.z=491;
2764                 temp2.x=1025;
2765                 temp2.y=75;
2766                 temp2.z=447;
2767
2768
2769                 weapons.owner[weapons.numweapons]=-1;
2770                 weapons.type[weapons.numweapons]=knife;
2771                 weapons.damage[weapons.numweapons]=0;
2772                 weapons.mass[weapons.numweapons]=1;
2773                 weapons.tipmass[weapons.numweapons]=1.2;
2774                 weapons.length[weapons.numweapons]=.25;
2775                 weapons.position[weapons.numweapons]=(temp+temp2)/2;
2776                 weapons.tippoint[weapons.numweapons]=(temp+temp2)/2;
2777
2778                 weapons.velocity[weapons.numweapons]=0.1;
2779                 weapons.tipvelocity[weapons.numweapons]=0.1;
2780                 weapons.missed[weapons.numweapons]=1;
2781                 weapons.hitsomething[weapons.numweapons]=0;
2782                 weapons.freetime[weapons.numweapons]=0;
2783                 weapons.firstfree[weapons.numweapons]=1;
2784                 weapons.physics[weapons.numweapons]=1;
2785
2786                 weapons.numweapons++;
2787             }
2788             break; case 40:
2789                 tutorialmaxtime=300;
2790             break; case 41:
2791                 tutorialmaxtime=300;
2792             break; case 42:
2793                 tutorialmaxtime=8;
2794             break; case 43:
2795                 tutorialmaxtime=300;
2796             break; case 44:
2797                 weapons.owner[0]=1;
2798                 player[0].weaponactive=-1;
2799                 player[0].num_weapons=0;
2800                 player[1].weaponactive=0;
2801                 player[1].num_weapons=1;
2802                 player[1].weaponids[0]=0;
2803
2804                 cananger=1;
2805                 canattack=1;
2806                 player[1].aitype=attacktypecutoff;
2807
2808                 tutorialmaxtime=300;
2809             break; case 45:
2810                 weapons.owner[0]=1;
2811                 player[0].weaponactive=-1;
2812                 player[0].num_weapons=0;
2813                 player[1].weaponactive=0;
2814                 player[1].num_weapons=1;
2815                 player[1].weaponids[0]=0;
2816
2817                 tutorialmaxtime=300;
2818             break; case 46:
2819                 weapons.owner[0]=1;
2820                 player[0].weaponactive=-1;
2821                 player[0].num_weapons=0;
2822                 player[1].weaponactive=0;
2823                 player[1].num_weapons=1;
2824                 player[1].weaponids[0]=0;
2825
2826                 weapons.type[0]=sword;
2827
2828                 tutorialmaxtime=300;
2829             break; case 47: {
2830                 tutorialmaxtime=10;
2831
2832                 XYZ temp,temp2;
2833
2834                 temp.x=1011;
2835                 temp.y=84;
2836                 temp.z=491;
2837                 temp2.x=1025;
2838                 temp2.y=75;
2839                 temp2.z=447;
2840
2841                 weapons.owner[weapons.numweapons]=-1;
2842                 weapons.type[weapons.numweapons]=sword;
2843                 weapons.damage[weapons.numweapons]=0;
2844                 weapons.mass[weapons.numweapons]=1;
2845                 weapons.tipmass[weapons.numweapons]=1.2;
2846                 weapons.length[weapons.numweapons]=.25;
2847                 weapons.position[weapons.numweapons]=(temp+temp2)/2;
2848                 weapons.tippoint[weapons.numweapons]=(temp+temp2)/2;
2849
2850                 weapons.velocity[weapons.numweapons]=0.1;
2851                 weapons.tipvelocity[weapons.numweapons]=0.1;
2852                 weapons.missed[weapons.numweapons]=1;
2853                 weapons.hitsomething[weapons.numweapons]=0;
2854                 weapons.freetime[weapons.numweapons]=0;
2855                 weapons.firstfree[weapons.numweapons]=1;
2856                 weapons.physics[weapons.numweapons]=1;
2857
2858                 weapons.owner[0]=1;
2859                 weapons.owner[1]=0;
2860                 player[0].weaponactive=0;
2861                 player[0].num_weapons=1;
2862                 player[0].weaponids[0]=1;
2863                 player[1].weaponactive=0;
2864                 player[1].num_weapons=1;
2865                 player[1].weaponids[0]=0;
2866
2867                 weapons.numweapons++;
2868             }
2869             break; case 48:
2870                 canattack=0;
2871                 cananger=0;
2872                 player[1].aitype=passivetype;
2873
2874                 tutorialmaxtime=15;
2875
2876                 weapons.owner[0]=1;
2877                 weapons.owner[1]=0;
2878                 player[0].weaponactive=0;
2879                 player[0].num_weapons=1;
2880                 player[0].weaponids[0]=1;
2881                 player[1].weaponactive=0;
2882                 player[1].num_weapons=1;
2883                 player[1].weaponids[0]=0;
2884
2885                 if(player[0].weaponactive!=-1)weapons.type[player[0].weaponids[player[0].weaponactive]]=staff;
2886                 else weapons.type[0]=staff;
2887
2888                 weapons.numweapons++;
2889             break; case 49:
2890                 canattack=0;
2891                 cananger=0;
2892                 player[1].aitype=passivetype;
2893
2894                 tutorialmaxtime=200;
2895
2896                 weapons.position[1]=1000;
2897                 weapons.tippoint[1]=1000;
2898
2899                 weapons.numweapons=1;
2900                 weapons.owner[0]=0;
2901                 player[1].weaponactive=-1;
2902                 player[1].num_weapons=0;
2903                 player[0].weaponactive=0;
2904                 player[0].num_weapons=1;
2905                 player[0].weaponids[0]=0;
2906
2907                 weapons.type[0]=knife;
2908
2909                 weapons.numweapons++;
2910             break; case 50: {
2911                 tutorialmaxtime=8;
2912
2913                 XYZ temp,temp2;
2914                 emit_sound_at(fireendsound, player[1].coords);
2915
2916                 for(int i=0;i<player[1].skeleton.num_joints;i++){
2917                     if(Random()%2==0){
2918                         if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
2919                         if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
2920                         if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
2921                         if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
2922                         Sprite::MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
2923                     }
2924                 }
2925
2926                 player[1].num_weapons=0;
2927                 player[1].weaponstuck=-1;
2928                 player[1].weaponactive=-1;
2929
2930                 weapons.numweapons=0;
2931
2932                 weapons.owner[0]=-1;
2933                 weapons.velocity[0]=0.1;
2934                 weapons.tipvelocity[0]=-0.1;
2935                 weapons.missed[0]=1;
2936                 weapons.hitsomething[0]=0;
2937                 weapons.freetime[0]=0;
2938                 weapons.firstfree[0]=1;
2939                 weapons.physics[0]=1;
2940             }
2941             break; case 51:
2942                 tutorialmaxtime=80000;
2943             break; default: break;
2944         }
2945         if(tutorialstage<=51)tutorialstagetime=0;
2946     }
2947
2948     //Tutorial success
2949     if(tutorialstagetime<tutorialmaxtime-3){
2950         switch(tutorialstage){
2951             case 3: if(deltah||deltav)tutorialsuccess+=multiplier;
2952             break; case 4: if(player[0].forwardkeydown||player[0].backkeydown||player[0].leftkeydown||player[0].rightkeydown)tutorialsuccess+=multiplier;
2953             break; case 5: if(player[0].jumpkeydown)tutorialsuccess=1;
2954             break; case 6: if(player[0].isCrouch())tutorialsuccess=1;
2955             break; case 7: if(player[0].targetanimation==rollanim)tutorialsuccess=1;
2956             break; case 8: if(player[0].targetanimation==sneakanim)tutorialsuccess+=multiplier;
2957             break; case 9: if(player[0].targetanimation==rabbitrunninganim||player[0].targetanimation==wolfrunninganim)tutorialsuccess+=multiplier;
2958             break; case 11: if(player[0].isWallJump())tutorialsuccess=1;
2959             break; case 12: if(player[0].targetanimation==flipanim)tutorialsuccess=1;
2960             break; case 15: if(player[0].targetanimation==upunchanim||player[0].targetanimation==winduppunchanim)tutorialsuccess=1;
2961             break; case 16: if(player[0].targetanimation==winduppunchanim)tutorialsuccess=1;
2962             break; case 17: if(player[0].targetanimation==spinkickanim)tutorialsuccess=1;
2963             break; case 18: if(player[0].targetanimation==sweepanim)tutorialsuccess=1;
2964             break; case 19: if(player[0].targetanimation==dropkickanim)tutorialsuccess=1;
2965             break; case 20: if(player[0].targetanimation==rabbitkickanim)tutorialsuccess=1;
2966             break; case 21: if(bonus==cannon)tutorialsuccess=1;
2967             break; case 22: if(bonus==spinecrusher)tutorialsuccess=1;
2968             break; case 23: if(player[0].targetanimation==walljumprightkickanim||player[0].targetanimation==walljumpleftkickanim)tutorialsuccess=1;
2969             break; case 24: if(player[0].targetanimation==rabbittacklinganim)tutorialsuccess=1;
2970             break; case 25: if(player[0].targetanimation==backhandspringanim)tutorialsuccess=1;
2971             break; case 28: if(animation[player[0].targetanimation].attack==reversed&&player[0].feint)tutorialsuccess=1;
2972             break; case 29:
2973                 if(player[0].escapednum==2){
2974                     tutorialsuccess=1;
2975                     reversaltrain=0;
2976                     cananger=0;
2977                     player[1].aitype=passivetype;
2978                 }
2979             break; case 33: if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
2980             break; case 34: if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
2981             break; case 35:
2982                 if(animation[player[0].targetanimation].attack==reversal){
2983                     tutorialsuccess=1;
2984                     reversaltrain=0;
2985                     cananger=0;
2986                     player[1].aitype=passivetype;
2987                 }
2988             break; case 40: if(player[0].num_weapons>0)tutorialsuccess=1;
2989             break; case 41: if(player[0].weaponactive==-1&&player[0].num_weapons>0)tutorialsuccess=1;
2990             break; case 43: if(player[0].targetanimation==knifeslashstartanim)tutorialsuccess=1;
2991             break; case 44: if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
2992             break; case 45: if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
2993             break; case 46: if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
2994             break; case 49: if(player[1].weaponstuck!=-1)tutorialsuccess=1;
2995             break; default: break;
2996         }
2997         if(tutorialsuccess>=1)tutorialstagetime=tutorialmaxtime-3;
2998
2999
3000         if(tutorialstagetime==tutorialmaxtime-3){
3001             emit_sound_np(consolesuccesssound);
3002         }
3003
3004         if(tutorialsuccess>=1){
3005             if(tutorialstage==34||tutorialstage==35)
3006                 tutorialstagetime=tutorialmaxtime-1;
3007         }
3008     }
3009
3010     if(tutorialstage<14||tutorialstage>=50){
3011         player[1].coords.y=300;
3012         player[1].velocity=0;
3013     }
3014 }
3015
3016
3017
3018 void Game::doDebugKeys(){
3019         float headprop,bodyprop,armprop,legprop;
3020     if(debugmode){
3021                 if(Input::isKeyPressed(SDLK_v)){
3022                         freeze=1-freeze;
3023                         if(freeze){
3024                                 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
3025                         }
3026                 }
3027
3028                 if(Input::isKeyPressed(SDLK_BACKQUOTE)){
3029                         console=1-console;
3030                         if(console){
3031                                 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
3032                         } else {
3033                                 freeze=0;
3034                                 waiting=false;
3035                         }
3036                 }
3037
3038                 if(console)
3039             freeze=1;
3040                 if(console&&!Input::isKeyDown(SDLK_LMETA)){
3041                         inputText(consoletext[0],&consoleselected,&consolechars[0]);
3042                         if(!waiting) {
3043                                 archiveselected=0;
3044                                 cmd_dispatch(this, consoletext[0]);
3045                                 if(consolechars[0]>0){
3046
3047                                         for(int k=14;k>=1;k--){
3048                                                 for(int j=0;j<255;j++){
3049                                                         consoletext[k][j]=consoletext[k-1][j];
3050                                                 }
3051                                                 consolechars[k]=consolechars[k-1];
3052                                         }
3053                                         for(int j=0;j<255;j++){
3054                                                 consoletext[0][j]=' ';
3055                                         }
3056                                         consolechars[0]=0;
3057                                         consoleselected=0;
3058                                 }
3059                         }
3060
3061                         consoleblinkdelay-=multiplier;
3062                         if(consoleblinkdelay<=0){
3063                                 consoleblinkdelay=.3;
3064                                 consoleblink=1-consoleblink;
3065                         }
3066                 }
3067
3068
3069
3070         if(Input::isKeyPressed(SDLK_h)){
3071             player[0].damagetolerance=200000;
3072             player[0].damage=0;
3073             player[0].burnt=0;
3074             player[0].permanentdamage=0;
3075             player[0].superpermanentdamage=0;
3076         }
3077
3078         if(Input::isKeyPressed(SDLK_j)){
3079             environment++;
3080             if(environment>2)
3081                 environment=0;
3082             Setenvironment(environment);
3083         }
3084
3085         if(Input::isKeyPressed(SDLK_c)){
3086             cameramode=1-cameramode;
3087         }
3088
3089         if(Input::isKeyPressed(SDLK_x)&&!Input::isKeyDown(SDLK_LSHIFT)){
3090             if(player[0].num_weapons>0){
3091                 if(weapons.type[player[0].weaponids[0]]==sword)weapons.type[player[0].weaponids[0]]=staff;
3092                 else if(weapons.type[player[0].weaponids[0]]==staff)weapons.type[player[0].weaponids[0]]=knife;
3093                 else weapons.type[player[0].weaponids[0]]=sword;
3094                 if(weapons.type[player[0].weaponids[0]]==sword){
3095                     weapons.mass[player[0].weaponids[0]]=1.5;
3096                     weapons.tipmass[player[0].weaponids[0]]=1;
3097                     weapons.length[player[0].weaponids[0]]=.8;
3098                 }
3099                 if(weapons.type[player[0].weaponids[0]]==staff){
3100                     weapons.mass[player[0].weaponids[0]]=2;
3101                     weapons.tipmass[player[0].weaponids[0]]=1;
3102                     weapons.length[player[0].weaponids[0]]=1.5;
3103                 }
3104
3105                 if(weapons.type[player[0].weaponids[0]]==knife){
3106                     weapons.mass[player[0].weaponids[0]]=1;
3107                     weapons.tipmass[player[0].weaponids[0]]=1.2;
3108                     weapons.length[player[0].weaponids[0]]=.25;
3109                 }
3110             }
3111         }
3112
3113         if(Input::isKeyPressed(SDLK_x)&&Input::isKeyDown(SDLK_LSHIFT)){
3114             int closest=-1;
3115             float closestdist=-1;
3116             float distance;
3117             if(numplayers>1)
3118                 for(int i=1;i<numplayers;i++){
3119                     distance=findDistancefast(&player[i].coords,&player[0].coords);
3120                     if(closestdist==-1||distance<closestdist){
3121                         closestdist=distance;
3122                         closest=i;
3123                     }
3124                 }
3125             if(closest!=-1){
3126                 if(player[closest].num_weapons){
3127                     if(weapons.type[player[closest].weaponids[0]]==sword)
3128                         weapons.type[player[closest].weaponids[0]]=staff;
3129                     else if(weapons.type[player[closest].weaponids[0]]==staff)
3130                         weapons.type[player[closest].weaponids[0]]=knife;
3131                     else weapons.type[player[closest].weaponids[0]]=sword;
3132                     if(weapons.type[player[closest].weaponids[0]]==sword){
3133                         weapons.mass[player[closest].weaponids[0]]=1.5;
3134                         weapons.tipmass[player[closest].weaponids[0]]=1;
3135                         weapons.length[player[closest].weaponids[0]]=.8;
3136                     }
3137                     if(weapons.type[player[0].weaponids[0]]==staff){
3138                         weapons.mass[player[0].weaponids[0]]=2;
3139                         weapons.tipmass[player[0].weaponids[0]]=1;
3140                         weapons.length[player[0].weaponids[0]]=1.5;
3141                     }
3142                     if(weapons.type[player[closest].weaponids[0]]==knife){
3143                         weapons.mass[player[closest].weaponids[0]]=1;
3144                         weapons.tipmass[player[closest].weaponids[0]]=1.2;
3145                         weapons.length[player[closest].weaponids[0]]=.25;
3146                     }
3147                 }
3148                 if(!player[closest].num_weapons){
3149                     player[closest].weaponids[0]=weapons.numweapons;
3150                     weapons.owner[weapons.numweapons]=closest;
3151                     weapons.type[weapons.numweapons]=knife;
3152                     weapons.damage[weapons.numweapons]=0;
3153                     weapons.numweapons++;
3154                     player[closest].num_weapons=1;
3155                     if(weapons.type[player[closest].weaponids[0]]==sword){
3156                         weapons.mass[player[closest].weaponids[0]]=1.5;
3157                         weapons.tipmass[player[closest].weaponids[0]]=1;
3158                         weapons.length[player[closest].weaponids[0]]=.8;
3159                     }
3160                     if(weapons.type[player[closest].weaponids[0]]==knife){
3161                         weapons.mass[player[closest].weaponids[0]]=1;
3162                         weapons.tipmass[player[closest].weaponids[0]]=1.2;
3163                         weapons.length[player[closest].weaponids[0]]=.25;
3164                     }
3165                 }
3166             }
3167         }
3168
3169         if(Input::isKeyDown(SDLK_u)){
3170             int closest=-1;
3171             float closestdist=-1;
3172             float distance;
3173             if(numplayers>1)
3174                 for(int i=1;i<numplayers;i++){
3175                     distance=findDistancefast(&player[i].coords,&player[0].coords);
3176                     if(closestdist==-1||distance<closestdist){
3177                         closestdist=distance;
3178                         closest=i;
3179                     }
3180                 }
3181             player[closest].rotation+=multiplier*50;
3182             player[closest].targetrotation=player[closest].rotation;
3183         }
3184
3185
3186         if(Input::isKeyPressed(SDLK_o)&&!Input::isKeyDown(SDLK_LSHIFT)){
3187             int closest=-1;
3188             float closestdist=-1;
3189             float distance;
3190             if(numplayers>1)
3191                 for(int i=1;i<numplayers;i++){
3192                     distance=findDistancefast(&player[i].coords,&player[0].coords);
3193                     if(closestdist==-1||distance<closestdist){
3194                         closestdist=distance;
3195                         closest=i;
3196                     }
3197                 }
3198             if(Input::isKeyDown(SDLK_LCTRL))closest=0;
3199
3200             if(closest!=-1){
3201                 player[closest].whichskin++;
3202                 if(player[closest].whichskin>9)
3203                     player[closest].whichskin=0;
3204                 if(player[closest].whichskin>2&&player[closest].creature==wolftype)
3205                     player[closest].whichskin=0;
3206
3207                 LoadTextureSave(creatureskin[player[closest].creature][player[closest].whichskin],
3208                         &player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
3209             }
3210
3211             if(player[closest].numclothes){
3212                 for(int i=0;i<player[closest].numclothes;i++){
3213                     tintr=player[closest].clothestintr[i];
3214                     tintg=player[closest].clothestintg[i];
3215                     tintb=player[closest].clothestintb[i];
3216                     AddClothes((char *)player[closest].clothes[i],0,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
3217                 }
3218                 player[closest].DoMipmaps();
3219             }
3220         }
3221
3222         if(Input::isKeyPressed(SDLK_o)&&Input::isKeyDown(SDLK_LSHIFT)){
3223             int closest=-1;
3224             float closestdist=-1;
3225             float distance;
3226             if(numplayers>1)
3227                 for(int i=1;i<numplayers;i++){
3228                     distance=findDistancefast(&player[i].coords,&player[0].coords);
3229                     if(closestdist==-1||distance<closestdist){
3230                         closestdist=distance;
3231                         closest=i;
3232                     }
3233                 }
3234             if(closest!=-1){
3235                 if(player[closest].creature==wolftype){
3236                     headprop=player[closest].proportionhead.x/1.1;
3237                     bodyprop=player[closest].proportionbody.x/1.1;
3238                     armprop=player[closest].proportionarms.x/1.1;
3239                     legprop=player[closest].proportionlegs.x/1.1;
3240                 }
3241
3242                 if(player[closest].creature==rabbittype){
3243                     headprop=player[closest].proportionhead.x/1.2;
3244                     bodyprop=player[closest].proportionbody.x/1.05;
3245                     armprop=player[closest].proportionarms.x/1.00;
3246                     legprop=player[closest].proportionlegs.x/1.1;
3247                 }
3248
3249
3250                 if(player[closest].creature==rabbittype){
3251                     player[closest].skeleton.id=closest;
3252                     player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure Wolf",(char *)":Data:Skeleton:Basic Figure Wolf Low",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Wolf.solid",(char *)":Data:Models:Wolf2.solid",(char *)":Data:Models:Wolf3.solid",(char *)":Data:Models:Wolf4.solid",(char *)":Data:Models:Wolf5.solid",(char *)":Data:Models:Wolf6.solid",(char *)":Data:Models:Wolf7.solid",(char *)":Data:Models:Wolflow.solid",(char *)":Data:Models:Belt.solid",0);
3253                     LoadTextureSave(":Data:Textures:Wolf.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[closest],&player[closest].skeleton.skinsize);
3254                     player[closest].whichskin=0;
3255                     player[closest].creature=wolftype;
3256
3257                     player[closest].proportionhead=1.1;
3258                     player[closest].proportionbody=1.1;
3259                     player[closest].proportionarms=1.1;
3260                     player[closest].proportionlegs=1.1;
3261                     player[closest].proportionlegs.y=1.1;
3262                     player[closest].scale=.23*5*player[0].scale;
3263
3264                     player[closest].damagetolerance=300;
3265                 }
3266                 else
3267                 {
3268                     player[closest].skeleton.id=closest;
3269                     player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
3270                     LoadTextureSave(":Data:Textures:Fur3.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
3271                     player[closest].whichskin=0;
3272                     player[closest].creature=rabbittype;
3273
3274                     player[closest].proportionhead=1.2;
3275                     player[closest].proportionbody=1.05;
3276                     player[closest].proportionarms=1.00;
3277                     player[closest].proportionlegs=1.1;
3278                     player[closest].proportionlegs.y=1.05;
3279                     player[closest].scale=.2*5*player[0].scale;
3280
3281                     player[closest].damagetolerance=200;
3282                 }
3283
3284                 if(player[closest].creature==wolftype){
3285                     player[closest].proportionhead=1.1*headprop;
3286                     player[closest].proportionbody=1.1*bodyprop;
3287                     player[closest].proportionarms=1.1*armprop;
3288                     player[closest].proportionlegs=1.1*legprop;
3289                 }
3290
3291                 if(player[closest].creature==rabbittype){
3292                     player[closest].proportionhead=1.2*headprop;
3293                     player[closest].proportionbody=1.05*bodyprop;
3294                     player[closest].proportionarms=1.00*armprop;
3295                     player[closest].proportionlegs=1.1*legprop;
3296                     player[closest].proportionlegs.y=1.05*legprop;
3297                 }
3298
3299             }
3300         }
3301
3302         if(Input::isKeyPressed(SDLK_b)&&!Input::isKeyDown(SDLK_LSHIFT)){
3303             slomo=1-slomo;
3304             slomodelay=1000;
3305         }
3306
3307
3308         if(((Input::isKeyPressed(SDLK_i)&&!Input::isKeyDown(SDLK_LSHIFT)))){
3309             int closest=-1;
3310             float closestdist=-1;
3311             float distance;
3312             XYZ flatfacing2,flatvelocity2;
3313             XYZ blah;
3314             if(numplayers>1)
3315                 for(int i=1;i<numplayers;i++){
3316                     distance=findDistancefast(&player[i].coords,&player[0].coords);
3317                     if(distance<144&&!player[i].headless)
3318                         if(closestdist==-1||distance<closestdist){
3319                             closestdist=distance;
3320                             closest=i;
3321                             blah = player[i].coords;
3322                         }
3323                 }
3324
3325             if(closest!=-1){
3326                 XYZ headspurtdirection;
3327                 //int i = player[closest].skeleton.jointlabels[head];
3328                 Joint& headjoint=playerJoint(closest,head);
3329                 for(int k=0;k<player[closest].skeleton.num_joints; k++){
3330                     if(!player[closest].skeleton.free)
3331                         flatvelocity2=player[closest].velocity;
3332                     if(player[closest].skeleton.free)
3333                         flatvelocity2=headjoint.velocity;
3334                     if(!player[closest].skeleton.free)
3335                         flatfacing2=DoRotation(DoRotation(DoRotation(headjoint.position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
3336                     if(player[closest].skeleton.free)
3337                         flatfacing2=headjoint.position*player[closest].scale+player[closest].coords;
3338                     flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
3339                     flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
3340                     flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
3341                     headspurtdirection=headjoint.position-playerJoint(closest,neck).position;
3342                     Normalise(&headspurtdirection);
3343                     Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, .6, 1);
3344                     flatvelocity2+=headspurtdirection*8;
3345                     Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2/2, 1,1,1, .16, 1);
3346                 }
3347                 Sprite::MakeSprite(cloudsprite, flatfacing2,flatvelocity2*0, .6,0,0, 1, .5);
3348
3349                 emit_sound_at(splattersound, blah);
3350                 emit_sound_at(breaksound2, blah, 100.);
3351
3352                 if(player[closest].skeleton.free==2)player[closest].skeleton.free=0;
3353                 player[closest].RagDoll(0);
3354                 player[closest].dead=2;
3355                 player[closest].headless=1;
3356                 player[closest].DoBloodBig(3,165);
3357
3358                 camerashake+=.3;
3359             }
3360         }
3361
3362         if(((Input::isKeyPressed(SDLK_i)&&Input::isKeyDown(SDLK_LSHIFT)))){
3363             int closest=-1;
3364             float closestdist=-1;
3365             float distance;
3366             XYZ flatfacing2,flatvelocity2;
3367             XYZ blah;
3368             if(numplayers>1)
3369                 for(int i=1;i<numplayers;i++){
3370                     distance=findDistancefast(&player[i].coords,&player[0].coords);
3371                     if(distance<144)
3372                         if(closestdist==-1||distance<closestdist){
3373                             closestdist=distance;
3374                             closest=i;
3375                             blah=player[i].coords;
3376                         }
3377                 }
3378
3379             if(closest!=-1){
3380                 emit_sound_at(splattersound, blah);
3381
3382                 emit_sound_at(breaksound2, blah);
3383
3384                 for(int i=0;i<player[closest].skeleton.num_joints; i++){
3385                     if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
3386                     if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
3387                     if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
3388                     if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
3389                     flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
3390                     flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
3391                     flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
3392                     Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, 3, 1);
3393                     Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2, 1,1,1, .3, 1);
3394                     Sprite::MakeSprite(cloudsprite, flatfacing2,flatvelocity2*0, .6,0,0, 1, .5);
3395                 }
3396
3397                 for(int i=0;i<player[closest].skeleton.num_joints; i++){
3398                     if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
3399                     if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
3400                     if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
3401                     if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
3402                     flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
3403                     flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
3404                     flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
3405                     Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, 3, 1);
3406                     Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2, 1,1,1, .4, 1);
3407                 }
3408
3409                 for(int i=0;i<player[closest].skeleton.num_joints; i++){
3410                     if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
3411                     if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
3412                     if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
3413                     if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
3414                     flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
3415                     flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
3416                     flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
3417                     Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2*2, 1,1,1, 3, 1);
3418                     Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2*2, 1,1,1, .4, 1);
3419                 }
3420
3421                 for(int i=0;i<player[closest].skeleton.num_joints; i++){
3422                     if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
3423                     if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
3424                     if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
3425                     if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
3426                     flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
3427                     flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
3428                     flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
3429                     Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2*2, 1,1,1, 3, 1);
3430                     Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2*2, 1,1,1, .4, 1);
3431                 }
3432
3433                 XYZ temppos;
3434                 for(int j=0;j<numplayers; j++){
3435                     if(j!=closest){
3436                         if(findDistancefast(&player[j].coords,&player[closest].coords)<25){
3437                             player[j].DoDamage((25-findDistancefast(&player[j].coords,&player[closest].coords))*60);
3438                             if(player[j].skeleton.free==2)
3439                                 player[j].skeleton.free=1;
3440                             player[j].skeleton.longdead=0;
3441                             player[j].RagDoll(0);
3442                             for(int i=0;i<player[j].skeleton.num_joints; i++){
3443                                 temppos=player[j].skeleton.joints[i].position+player[j].coords;
3444                                 if(findDistancefast(&temppos,&player[closest].coords)<25){
3445                                     flatvelocity2=temppos-player[closest].coords;
3446                                     Normalise(&flatvelocity2);
3447                                     player[j].skeleton.joints[i].velocity+=flatvelocity2*((20-findDistancefast(&temppos,&player[closest].coords))*20);
3448                                 }
3449                             }
3450                         }
3451                     }
3452                 }
3453
3454                 player[closest].DoDamage(10000);
3455                 player[closest].RagDoll(0);
3456                 player[closest].dead=2;
3457                 player[closest].coords=20;
3458                 player[closest].skeleton.free=2;
3459
3460                 camerashake+=.6;
3461
3462             }
3463         }
3464
3465         if(Input::isKeyPressed(SDLK_f)){
3466             player[0].onfire=1-player[0].onfire;
3467             if(player[0].onfire){
3468                 player[0].CatchFire();
3469             }
3470             if(!player[0].onfire){
3471                 emit_sound_at(fireendsound, player[0].coords);
3472                 pause_sound(stream_firesound);
3473             }
3474         }
3475
3476         if(Input::isKeyPressed(SDLK_n)&&!Input::isKeyDown(SDLK_LCTRL)){
3477             //if(!player[0].skeleton.free)player[0].damage+=500;
3478             player[0].RagDoll(0);
3479             //player[0].spurt=1;
3480             //player[0].DoDamage(1000);
3481
3482             emit_sound_at(whooshsound, player[0].coords, 128.);
3483         }
3484
3485         if(Input::isKeyPressed(SDLK_n)&&Input::isKeyDown(SDLK_LCTRL)){
3486             int closest=-1;
3487             float closestdist=-1;
3488             float distance;
3489             for(int i=0;i<objects.numobjects;i++){
3490                 if(objects.type[i]==treeleavestype){
3491                     objects.scale[i]*=.9;
3492                 }
3493             }
3494         }
3495
3496         if(Input::isKeyPressed(SDLK_m)&&Input::isKeyDown(SDLK_LSHIFT)){
3497             editorenabled=1-editorenabled;
3498             if(editorenabled){
3499                 player[0].damagetolerance=100000;
3500             } else {
3501                 player[0].damagetolerance=200;
3502             }
3503             player[0].damage=0; // these lines were in both if and else, but I think they would better fit in the if
3504             player[0].permanentdamage=0;
3505             player[0].superpermanentdamage=0;
3506             player[0].bloodloss=0;
3507             player[0].deathbleeding=0;
3508         }
3509
3510         //skip level
3511         if(whichlevel!=-2&&Input::isKeyPressed(SDLK_k)&&Input::isKeyDown(SDLK_LSHIFT)&&!editorenabled){
3512             targetlevel++;
3513             if(targetlevel>numchallengelevels-1)targetlevel=0;
3514             loading=1;
3515             leveltime=5;
3516         }
3517
3518         if(editorenabled){
3519             if(Input::isKeyPressed(SDLK_DELETE)&&Input::isKeyDown(SDLK_LSHIFT)){
3520                 int closest=-1;
3521                 float closestdist=-1;
3522                 float distance;
3523                 if(numplayers>1)
3524                     for(int i=1;i<numplayers;i++){
3525                         distance=findDistancefast(&player[i].coords,&player[0].coords);
3526                         if(closestdist==-1||distance<closestdist){
3527                             closestdist=distance;
3528                             closest=i;
3529                         }
3530                     }
3531                 if(closestdist>0&&closest>=0){
3532                     //player[closest]=player[numplayers-1];
3533                     //player[closest].skeleton=player[numplayers-1].skeleton;
3534                     numplayers--;
3535                 }
3536             }
3537
3538             if(Input::isKeyPressed(SDLK_DELETE)&&Input::isKeyDown(SDLK_LCTRL)){
3539                 int closest=-1;
3540                 float closestdist=-1;
3541                 float distance;
3542                 if(max_objects>1)
3543                     for(int i=1;i<max_objects;i++){
3544                         distance=findDistancefast(&objects.position[i],&player[0].coords);
3545                         if(closestdist==-1||distance<closestdist){
3546                             closestdist=distance;
3547                             closest=i;
3548                         }
3549                     }
3550                 if(closestdist>0&&closest>=0){
3551                     objects.position[closest].y-=500;
3552                 }
3553             }
3554
3555             if(Input::isKeyPressed(SDLK_m)&&Input::isKeyDown(SDLK_LSHIFT)){
3556                 //drawmode++;
3557                 //if(drawmode>2)drawmode=0;
3558                 if(objects.numobjects<max_objects-1){
3559                     XYZ boxcoords;
3560                     boxcoords.x=player[0].coords.x;
3561                     boxcoords.z=player[0].coords.z;
3562                     boxcoords.y=player[0].coords.y-3;
3563                     if(editortype==bushtype)boxcoords.y=player[0].coords.y-.5;
3564                     if(editortype==firetype)boxcoords.y=player[0].coords.y-.5;
3565                     //objects.MakeObject(abs(Random()%3),boxcoords,Random()%360);
3566                     float temprotat,temprotat2;
3567                     temprotat=editorrotation;
3568                     temprotat2=editorrotation2;
3569                     if(temprotat<0||editortype==bushtype)temprotat=Random()%360;
3570                     if(temprotat2<0)temprotat2=Random()%360;
3571
3572                     objects.MakeObject(editortype,boxcoords,(int)temprotat-((int)temprotat)%30,(int)temprotat2,editorsize);
3573                     if(editortype==treetrunktype)
3574                         objects.MakeObject(treeleavestype,boxcoords,Random()%360*(temprotat2<2)+(int)editorrotation-((int)editorrotation)%30,editorrotation2,editorsize);
3575                 }
3576             }
3577
3578             if(Input::isKeyPressed(SDLK_p)&&Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
3579                 if(numplayers<maxplayers-1){
3580                     player[numplayers].scale=.2*5*player[0].scale;
3581                     player[numplayers].creature=rabbittype;
3582                     player[numplayers].howactive=editoractive;
3583                     player[numplayers].skeleton.id=numplayers;
3584                     player[numplayers].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
3585
3586                     //texsize=512*512*3/texdetail/texdetail;
3587                     //if(!player[numplayers].loaded)player[numplayers].skeleton.skinText = new GLubyte[texsize];
3588                     //player[numplayers].skeleton.skinText.resize(texsize);
3589
3590                     int k=abs(Random()%2)+1;
3591                     if(k==0){
3592                         LoadTextureSave(":Data:Textures:Fur3.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
3593                         player[numplayers].whichskin=0;
3594                     }
3595                     else if(k==1){
3596                         LoadTextureSave(":Data:Textures:Fur.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
3597                         player[numplayers].whichskin=1;
3598                     }
3599                     else {
3600                         LoadTextureSave(":Data:Textures:Fur2.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
3601                         player[numplayers].whichskin=2;
3602                     }
3603
3604                     LoadTexture(":Data:Textures:Belt.png",&player[numplayers].skeleton.drawmodelclothes.textureptr,1,1);
3605                     player[numplayers].power=1;
3606                     player[numplayers].speedmult=1;
3607                     player[numplayers].currentanimation=bounceidleanim;
3608                     player[numplayers].targetanimation=bounceidleanim;
3609                     player[numplayers].currentframe=0;
3610                     player[numplayers].targetframe=1;
3611                     player[numplayers].target=0;
3612                     player[numplayers].bled=0;
3613                     player[numplayers].speed=1+(float)(Random()%100)/1000;
3614
3615                     player[numplayers].targetrotation=player[0].targetrotation;
3616                     player[numplayers].rotation=player[0].rotation;
3617
3618                     player[numplayers].velocity=0;
3619                     player[numplayers].coords=player[0].coords;
3620                     player[numplayers].oldcoords=player[numplayers].coords;
3621                     player[numplayers].realoldcoords=player[numplayers].coords;
3622
3623                     player[numplayers].id=numplayers;
3624                     player[numplayers].skeleton.id=numplayers;
3625                     player[numplayers].updatedelay=0;
3626                     player[numplayers].normalsupdatedelay=0;
3627
3628                     player[numplayers].aitype=passivetype;
3629
3630                     if(player[0].creature==wolftype){
3631                         headprop=player[0].proportionhead.x/1.1;
3632                         bodyprop=player[0].proportionbody.x/1.1;
3633                         armprop=player[0].proportionarms.x/1.1;
3634                         legprop=player[0].proportionlegs.x/1.1;
3635                     }
3636
3637                     if(player[0].creature==rabbittype){
3638                         headprop=player[0].proportionhead.x/1.2;
3639                         bodyprop=player[0].proportionbody.x/1.05;
3640                         armprop=player[0].proportionarms.x/1.00;
3641                         legprop=player[0].proportionlegs.x/1.1;
3642                     }
3643
3644                     if(player[numplayers].creature==wolftype){
3645                         player[numplayers].proportionhead=1.1*headprop;
3646                         player[numplayers].proportionbody=1.1*bodyprop;
3647                         player[numplayers].proportionarms=1.1*armprop;
3648                         player[numplayers].proportionlegs=1.1*legprop;
3649                     }
3650
3651                     if(player[numplayers].creature==rabbittype){
3652                         player[numplayers].proportionhead=1.2*headprop;
3653                         player[numplayers].proportionbody=1.05*bodyprop;
3654                         player[numplayers].proportionarms=1.00*armprop;
3655                         player[numplayers].proportionlegs=1.1*legprop;
3656                         player[numplayers].proportionlegs.y=1.05*legprop;
3657                     }
3658
3659                     player[numplayers].headless=0;
3660                     player[numplayers].onfire=0;
3661
3662                     if(cellophane){
3663                         player[numplayers].proportionhead.z=0;
3664                         player[numplayers].proportionbody.z=0;
3665                         player[numplayers].proportionarms.z=0;
3666                         player[numplayers].proportionlegs.z=0;
3667                     }
3668
3669                     player[numplayers].tempanimation.Load((char *)"Tempanim",0,0);
3670
3671                     player[numplayers].damagetolerance=200;
3672
3673                     player[numplayers].protectionhead=player[0].protectionhead;
3674                     player[numplayers].protectionhigh=player[0].protectionhigh;
3675                     player[numplayers].protectionlow=player[0].protectionlow;
3676                     player[numplayers].armorhead=player[0].armorhead;
3677                     player[numplayers].armorhigh=player[0].armorhigh;
3678                     player[numplayers].armorlow=player[0].armorlow;
3679                     player[numplayers].metalhead=player[0].metalhead;
3680                     player[numplayers].metalhigh=player[0].metalhigh;
3681                     player[numplayers].metallow=player[0].metallow;
3682
3683                     player[numplayers].immobile=player[0].immobile;
3684
3685                     player[numplayers].numclothes=player[0].numclothes;
3686                     if(player[numplayers].numclothes)
3687                         for(int i=0;i<player[numplayers].numclothes;i++){
3688                             strcpy(player[numplayers].clothes[i], player[0].clothes[i]);
3689                             player[numplayers].clothestintr[i]=player[0].clothestintr[i];
3690                             player[numplayers].clothestintg[i]=player[0].clothestintg[i];
3691                             player[numplayers].clothestintb[i]=player[0].clothestintb[i];
3692                             tintr=player[numplayers].clothestintr[i];
3693                             tintg=player[numplayers].clothestintg[i];
3694                             tintb=player[numplayers].clothestintb[i];
3695                             AddClothes((char *)player[numplayers].clothes[i],0,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
3696                         }
3697                     if(player[numplayers].numclothes){
3698                         player[numplayers].DoMipmaps();
3699                     }
3700
3701                     player[numplayers].power=player[0].power;
3702                     player[numplayers].speedmult=player[0].speedmult;
3703
3704                     player[numplayers].damage=0;
3705                     player[numplayers].permanentdamage=0;
3706                     player[numplayers].superpermanentdamage=0;
3707                     player[numplayers].deathbleeding=0;
3708                     player[numplayers].bleeding=0;
3709                     player[numplayers].numwaypoints=0;
3710                     player[numplayers].waypoint=0;
3711                     player[numplayers].jumppath=0;
3712                     player[numplayers].weaponstuck=-1;
3713                     player[numplayers].weaponactive=-1;
3714                     player[numplayers].num_weapons=0;
3715                     player[numplayers].bloodloss=0;
3716                     player[numplayers].dead=0;
3717
3718                     player[numplayers].loaded=1;
3719
3720                     numplayers++;
3721                 }
3722             }
3723
3724             if(Input::isKeyPressed(SDLK_p)&&Input::isKeyDown(SDLK_LSHIFT)){
3725                 if(player[numplayers-1].numwaypoints<90){
3726                     player[numplayers-1].waypoints[player[numplayers-1].numwaypoints]=player[0].coords;
3727                     player[numplayers-1].waypointtype[player[numplayers-1].numwaypoints]=editorpathtype;
3728                     player[numplayers-1].numwaypoints++;
3729                 }
3730             }
3731
3732             if(Input::isKeyPressed(SDLK_p)&&Input::isKeyDown(SDLK_LCTRL)){
3733                 if(numpathpoints<30){
3734                     bool connected,alreadyconnected;
3735                     connected=0;
3736                     if(numpathpoints>1)
3737                         for(int i=0;i<numpathpoints;i++){
3738                             if(findDistancefast(&pathpoint[i],&player[0].coords)<.5&&i!=pathpointselected&&!connected){
3739                                 alreadyconnected=0;
3740                                 for(int j=0;j<numpathpointconnect[pathpointselected];j++){
3741                                     if(pathpointconnect[pathpointselected][j]==i)alreadyconnected=1;
3742                                 }
3743                                 if(!alreadyconnected){
3744                                     numpathpointconnect[pathpointselected]++;
3745                                     connected=1;
3746                                     pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected]-1]=i;
3747                                 }
3748                             }
3749                         }
3750                     if(!connected){
3751                         numpathpoints++;
3752                         pathpoint[numpathpoints-1]=player[0].coords;
3753                         numpathpointconnect[numpathpoints-1]=0;
3754                         if(numpathpoints>1&&pathpointselected!=-1){
3755                             numpathpointconnect[pathpointselected]++;
3756                             pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected]-1]=numpathpoints-1;
3757                         }
3758                         pathpointselected=numpathpoints-1;
3759                     }
3760                 }
3761             }
3762
3763             if(Input::isKeyPressed(SDLK_PERIOD)){
3764                 pathpointselected++;
3765                 if(pathpointselected>=numpathpoints)pathpointselected=-1;
3766             }
3767             if(Input::isKeyPressed(SDLK_COMMA)&&!Input::isKeyDown(SDLK_LSHIFT)){
3768                 pathpointselected--;
3769                 if(pathpointselected<=-2)
3770                     pathpointselected=numpathpoints-1;
3771             }
3772             if(Input::isKeyPressed(SDLK_COMMA)&&Input::isKeyDown(SDLK_LSHIFT)){
3773                 if(pathpointselected!=-1){
3774                     numpathpoints--;
3775                     pathpoint[pathpointselected]=pathpoint[numpathpoints];
3776                     numpathpointconnect[pathpointselected]=numpathpointconnect[numpathpoints];
3777                     for(int i=0;i<numpathpointconnect[pathpointselected];i++){
3778                         pathpointconnect[pathpointselected][i]=pathpointconnect[numpathpoints][i];
3779                     }
3780                     for(int i=0;i<numpathpoints;i++){
3781                         for(int j=0;j<numpathpointconnect[i];j++){
3782                             if(pathpointconnect[i][j]==pathpointselected){
3783                                 pathpointconnect[i][j]=pathpointconnect[i][numpathpointconnect[i]-1];
3784                                 numpathpointconnect[i]--;
3785                             }
3786                             if(pathpointconnect[i][j]==numpathpoints){
3787                                 pathpointconnect[i][j]=pathpointselected;
3788                             }
3789                         }
3790                     }
3791                     pathpointselected=numpathpoints-1;
3792                 }
3793             }
3794
3795             if(Input::isKeyPressed(SDLK_LEFT)&&Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
3796                 editortype--;
3797                 if(editortype==treeleavestype||editortype==10)editortype--;
3798                 if(editortype<0)editortype=firetype;
3799             }
3800
3801             if(Input::isKeyPressed(SDLK_RIGHT)&&Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
3802                 editortype++;
3803                 if(editortype==treeleavestype||editortype==10)editortype++;
3804                 if(editortype>firetype)editortype=0;
3805             }
3806
3807             if(Input::isKeyDown(SDLK_LEFT)&&!Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
3808                 editorrotation-=multiplier*100;
3809                 if(editorrotation<-.01)editorrotation=-.01;
3810             }
3811
3812             if(Input::isKeyDown(SDLK_RIGHT)&&!Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
3813                 editorrotation+=multiplier*100;
3814             }
3815
3816             if(Input::isKeyDown(SDLK_UP)&&!Input::isKeyDown(SDLK_LCTRL)){
3817                 editorsize+=multiplier;
3818             }
3819
3820             if(Input::isKeyDown(SDLK_DOWN)&&!Input::isKeyDown(SDLK_LCTRL)){
3821                 editorsize-=multiplier;
3822                 if(editorsize<.1)editorsize=.1;
3823             }
3824
3825
3826             if(Input::isKeyPressed(SDLK_LEFT)&&Input::isKeyDown(SDLK_LSHIFT)&&Input::isKeyDown(SDLK_LCTRL)){
3827                 mapradius-=multiplier*10;
3828             }
3829
3830             if(Input::isKeyPressed(SDLK_RIGHT)&&Input::isKeyDown(SDLK_LSHIFT)&&Input::isKeyDown(SDLK_LCTRL)){
3831                 mapradius+=multiplier*10;
3832             }
3833             if(Input::isKeyDown(SDLK_UP)&&Input::isKeyDown(SDLK_LCTRL)){
3834                 editorrotation2+=multiplier*100;
3835             }
3836
3837             if(Input::isKeyDown(SDLK_DOWN)&&Input::isKeyDown(SDLK_LCTRL)){
3838                 editorrotation2-=multiplier*100;
3839                 if(editorrotation2<-.01)editorrotation2=-.01;
3840             }
3841             if(Input::isKeyPressed(SDLK_DELETE)&&objects.numobjects&&Input::isKeyDown(SDLK_LSHIFT)){
3842                 int closest=-1;
3843                 float closestdist=-1;
3844                 float distance;
3845                 for(int i=0;i<objects.numobjects;i++){
3846                     distance=findDistancefast(&objects.position[i],&player[0].coords);
3847                     if(closestdist==-1||distance<closestdist){
3848                         closestdist=distance;
3849                         closest=i;
3850                     }
3851                 }
3852                 if(closestdist>0&&closest>=0)objects.DeleteObject(closest);
3853             }
3854         }
3855     }
3856 }
3857
3858
3859
3860 void Game::doJumpReversals(){
3861     for(int k=0;k<numplayers;k++)
3862         for(int i=k;i<numplayers;i++){
3863             if(i==k)continue;
3864             if(     player[k].skeleton.free==0&&
3865                     player[i].skeleton.oldfree==0&&
3866                     (player[i].targetanimation==jumpupanim||
3867                      player[k].targetanimation==jumpupanim)&&
3868                     (player[i].aitype==playercontrolled||
3869                      player[k].aitype==playercontrolled)&&
3870                     (player[i].aitype==attacktypecutoff&&player[i].stunned<=0||
3871                      player[k].aitype==attacktypecutoff&&player[k].stunned<=0)){
3872                 if(     findDistancefast(&player[i].coords,&player[k].coords)<10*sq((player[i].scale+player[k].scale)*2.5)&&
3873                         findDistancefastflat(&player[i].coords,&player[k].coords)<2*sq((player[i].scale+player[k].scale)*2.5)){
3874                     //TODO: refactor two huge similar ifs
3875                     if(player[i].targetanimation==jumpupanim&&
3876                             player[k].targetanimation!=getupfrombackanim&&
3877                             player[k].targetanimation!=getupfromfrontanim&&
3878                             animation[player[k].targetanimation].height==middleheight&&
3879                             normaldotproduct(player[i].velocity,player[k].coords-player[i].coords)<0&&
3880                             (player[k].aitype==playercontrolled&&player[k].attackkeydown||
3881                              player[k].aitype!=playercontrolled)){
3882                         player[i].victim=&player[k];
3883                         player[i].velocity=0;
3884                         player[i].currentanimation=jumpreversedanim;
3885                         player[i].targetanimation=jumpreversedanim;
3886                         player[i].currentframe=0;
3887                         player[i].targetframe=1;
3888                         player[i].targettilt2=0;
3889                         player[k].victim=&player[i];
3890                         player[k].velocity=0;
3891                         player[k].currentanimation=jumpreversalanim;
3892                         player[k].targetanimation=jumpreversalanim;
3893                         player[k].currentframe=0;
3894                         player[k].targetframe=1;
3895                         player[k].targettilt2=0;
3896                         if(player[i].coords.y<player[k].coords.y+1){
3897                             player[i].currentanimation=rabbitkickreversedanim;
3898                             player[i].targetanimation=rabbitkickreversedanim;
3899                             player[i].currentframe=1;
3900                             player[i].targetframe=2;
3901                             player[k].currentanimation=rabbitkickreversalanim;
3902                             player[k].targetanimation=rabbitkickreversalanim;
3903                             player[k].currentframe=1;
3904                             player[k].targetframe=2;
3905                         }
3906                         player[i].target=0;
3907                         player[k].oldcoords=player[k].coords;
3908                         player[i].coords=player[k].coords;
3909                         player[k].targetrotation=player[i].targetrotation;
3910                         player[k].rotation=player[i].targetrotation;
3911                         if(player[k].aitype==attacktypecutoff)
3912                             player[k].stunned=.5;
3913                     }
3914                     if(player[k].targetanimation==jumpupanim&&
3915                             player[i].targetanimation!=getupfrombackanim&&
3916                             player[i].targetanimation!=getupfromfrontanim&&
3917                             animation[player[i].targetanimation].height==middleheight&&
3918                             normaldotproduct(player[k].velocity,player[i].coords-player[k].coords)<0&&
3919                             ((player[i].aitype==playercontrolled&&player[i].attackkeydown)||
3920                              player[i].aitype!=playercontrolled)){
3921                         player[k].victim=&player[i];
3922                         player[k].velocity=0;
3923                         player[k].currentanimation=jumpreversedanim;
3924                         player[k].targetanimation=jumpreversedanim;
3925                         player[k].currentframe=0;
3926                         player[k].targetframe=1;
3927                         player[k].targettilt2=0;
3928                         player[i].victim=&player[k];
3929                         player[i].velocity=0;
3930                         player[i].currentanimation=jumpreversalanim;
3931                         player[i].targetanimation=jumpreversalanim;
3932                         player[i].currentframe=0;
3933                         player[i].targetframe=1;
3934                         player[i].targettilt2=0;
3935                         if(player[k].coords.y<player[i].coords.y+1){
3936                             player[k].targetanimation=rabbitkickreversedanim;
3937                             player[k].currentanimation=rabbitkickreversedanim;
3938                             player[i].currentanimation=rabbitkickreversalanim;
3939                             player[i].targetanimation=rabbitkickreversalanim;
3940                             player[k].currentframe=1;
3941                             player[k].targetframe=2;
3942                             player[i].currentframe=1;
3943                             player[i].targetframe=2;
3944                         }
3945                         player[k].target=0;
3946                         player[i].oldcoords=player[i].coords;
3947                         player[k].coords=player[i].coords;
3948                         player[i].targetrotation=player[k].targetrotation;
3949                         player[i].rotation=player[k].targetrotation;
3950                         if(player[i].aitype==attacktypecutoff)
3951                             player[i].stunned=.5;
3952                     }
3953                 }
3954             }
3955         }
3956 }
3957
3958 void Game::doAerialAcrobatics(){
3959         static XYZ facing,flatfacing;
3960     for(int k=0;k<numplayers;k++){
3961         player[k].turnspeed=500;
3962
3963         if((player[k].isRun()&&
3964                     ((player[k].targetrotation!=rabbitrunninganim&&
3965                       player[k].targetrotation!=wolfrunninganim)||
3966                      player[k].targetframe==4))||
3967                 player[k].targetanimation==removeknifeanim||
3968                 player[k].targetanimation==crouchremoveknifeanim||
3969                 player[k].targetanimation==flipanim||
3970                 player[k].targetanimation==fightsidestep||
3971                 player[k].targetanimation==walkanim){
3972             player[k].rotation=stepTowardf(player[k].rotation, player[k].targetrotation, multiplier*player[k].turnspeed);
3973         }
3974
3975
3976         if(player[k].isStop()||
3977                 player[k].isLanding()||
3978                 player[k].targetanimation==staggerbackhighanim||
3979                 (player[k].targetanimation==sneakanim&&player[k].currentanimation==sneakanim)||
3980                 player[k].targetanimation==staggerbackhardanim||
3981                 player[k].targetanimation==backhandspringanim||
3982                 player[k].targetanimation==dodgebackanim||
3983                 player[k].targetanimation==rollanim||
3984                 (animation[player[k].targetanimation].attack&&
3985                  player[k].targetanimation!=rabbitkickanim&&
3986                  (player[k].targetanimation!=crouchstabanim||player[k].hasvictim)&&
3987                  (player[k].targetanimation!=swordgroundstabanim||player[k].hasvictim))){
3988             player[k].rotation=stepTowardf(player[k].rotation, player[k].targetrotation, multiplier*player[k].turnspeed*2);
3989         }
3990
3991         if(player[k].targetanimation==sneakanim&&player[k].currentanimation!=sneakanim){
3992             player[k].rotation=stepTowardf(player[k].rotation, player[k].targetrotation, multiplier*player[k].turnspeed*4);
3993         }
3994
3995         /*if(player[k].aitype!=passivetype||(findDistancefast(&player[k].coords,&viewer)<viewdistance*viewdistance))*/
3996         player[k].DoStuff();
3997         if(player[k].immobile&&k!=0)
3998             player[k].coords=player[k].realoldcoords;
3999
4000         //if player's position has changed (?)
4001         if(findDistancefast(&player[k].coords,&player[k].realoldcoords)>0&&
4002                 !player[k].skeleton.free&&
4003                 player[k].targetanimation!=climbanim&&
4004                 player[k].targetanimation!=hanganim){
4005             XYZ lowpoint,lowpointtarget,lowpoint2,lowpointtarget2,lowpoint3,lowpointtarget3,lowpoint4,lowpointtarget4,lowpoint5,lowpointtarget5,lowpoint6,lowpointtarget6,lowpoint7,lowpointtarget7,colpoint,colpoint2;
4006             int whichhit;
4007             bool tempcollide=0;
4008
4009             if(player[k].collide<-.3)
4010                 player[k].collide=-.3;
4011             if(player[k].collide>1)
4012                 player[k].collide=1;
4013             player[k].collide-=multiplier*30;
4014
4015             //clip to terrain
4016             player[k].coords.y=max(player[k].coords.y, terrain.getHeight(player[k].coords.x,player[k].coords.z));
4017
4018             for(int l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
4019                 int i=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
4020                 if(objects.type[i]!=rocktype||
4021                         objects.scale[i]>.5&&player[k].aitype==playercontrolled||
4022                         objects.position[i].y>player[k].coords.y){
4023                     lowpoint=player[k].coords;
4024                     if(player[k].targetanimation!=jumpupanim&&
4025                             player[k].targetanimation!=jumpdownanim&&
4026                             !player[k].isFlip())
4027                         lowpoint.y+=1.25;
4028                     else
4029                         lowpoint.y+=1.3;
4030                     if(     player[k].coords.y<terrain.getHeight(player[k].coords.x,player[k].coords.z)&&
4031                             player[k].coords.y>terrain.getHeight(player[k].coords.x,player[k].coords.z)-.1)
4032                         player[k].coords.y=terrain.getHeight(player[k].coords.x,player[k].coords.z);
4033                     if(player[k].SphereCheck(&lowpoint, 1.3, &colpoint, &objects.position[i], &objects.rotation[i], &objects.model[i])!=-1){
4034                         flatfacing=lowpoint-player[k].coords;
4035                         player[k].coords=lowpoint;
4036                         player[k].coords.y-=1.3;
4037                         player[k].collide=1;
4038                         tempcollide=1;
4039                         //wall jumps
4040                         //TODO: refactor four similar blocks
4041                         if(player[k].aitype==playercontrolled&&
4042                                 (player[k].targetanimation==jumpupanim||
4043                                  player[k].targetanimation==jumpdownanim||
4044                                  player[k].isFlip())&&
4045                                 !player[k].jumptogglekeydown&&
4046                                 player[k].jumpkeydown){
4047                             lowpointtarget=lowpoint+DoRotation(player[k].facing,0,-90,0)*1.5;
4048                             XYZ tempcoords1=lowpoint;
4049                             whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
4050                             if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
4051                                 setAnimation(k,walljumpleftanim);
4052                                 emit_sound_at(movewhooshsound, player[k].coords);
4053                                 if(k==0)
4054                                     pause_sound(whooshsound);
4055
4056                                 lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
4057                                 player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
4058                                 if(lowpointtarget.z<0)
4059                                     player[k].rotation=180-player[k].rotation;
4060                                 player[k].targetrotation=player[k].rotation;
4061                                 player[k].lowrotation=player[k].rotation;
4062                                 if(k==0)
4063                                     numwallflipped++;
4064                             }
4065                             else
4066                             {
4067                                 lowpoint=tempcoords1;
4068                                 lowpointtarget=lowpoint+DoRotation(player[k].facing,0,90,0)*1.5;
4069                                 whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
4070                                 if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
4071                                     setAnimation(k,walljumprightanim);
4072                                     emit_sound_at(movewhooshsound, player[k].coords);
4073                                     if(k==0)pause_sound(whooshsound);
4074
4075                                     lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
4076                                     player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
4077                                     if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
4078                                     player[k].targetrotation=player[k].rotation;
4079                                     player[k].lowrotation=player[k].rotation;
4080                                     if(k==0)numwallflipped++;
4081                                 }
4082                                 else
4083                                 {
4084                                     lowpoint=tempcoords1;
4085                                     lowpointtarget=lowpoint+player[k].facing*2;
4086                                     whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
4087                                     if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
4088                                         setAnimation(k,walljumpbackanim);
4089                                         emit_sound_at(movewhooshsound, player[k].coords);
4090                                         if(k==0)pause_sound(whooshsound);
4091
4092                                         lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
4093                                         player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
4094                                         if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
4095                                         player[k].targetrotation=player[k].rotation;
4096                                         player[k].lowrotation=player[k].rotation;
4097                                         if(k==0)numwallflipped++;
4098                                     }
4099                                     else
4100                                     {
4101                                         lowpoint=tempcoords1;
4102                                         lowpointtarget=lowpoint-player[k].facing*2;
4103                                         whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
4104                                         if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
4105                                             setAnimation(k,walljumpfrontanim);
4106                                             emit_sound_at(movewhooshsound, player[k].coords);
4107                                             if(k==0)pause_sound(whooshsound);
4108
4109                                             lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
4110                                             player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
4111                                             if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
4112                                             player[k].rotation+=180;
4113                                             player[k].targetrotation=player[k].rotation;
4114                                             player[k].lowrotation=player[k].rotation;
4115                                             if(k==0)numwallflipped++;
4116                                         }
4117                                     }
4118                                 }
4119                             }
4120                         }
4121                     }
4122                 }
4123                 else if(objects.type[i]==rocktype){
4124                     lowpoint2=player[k].coords;
4125                     lowpoint=player[k].coords;
4126                     lowpoint.y+=2;
4127                     if(objects.model[i].LineCheck(&lowpoint,&lowpoint2,&colpoint,&objects.position[i],&objects.rotation[i])!=-1){
4128                         player[k].coords=colpoint;
4129                         player[k].collide=1;
4130                         tempcollide=1;
4131
4132                         if(player[k].targetanimation==jumpdownanim||player[k].isFlip()){
4133                             //flipped into a rock
4134                             if(player[k].isFlip()&&animation[player[k].targetanimation].label[player[k].targetframe]==7)
4135                                 player[k].RagDoll(0);
4136
4137                             if(player[k].targetanimation==jumpupanim){
4138                                 player[k].jumppower=-4;
4139                                 player[k].targetanimation=player[k].getIdle();
4140                             }
4141                             player[k].target=0;
4142                             player[k].targetframe=0;
4143                             player[k].onterrain=1;
4144
4145                             if(player[k].id==0){
4146                                 pause_sound(whooshsound);
4147                                 OPENAL_SetVolume(channels[whooshsound], 0);
4148                             }
4149
4150                             //landing
4151                             if((player[k].targetanimation==jumpdownanim||player[k].isFlip())&&!player[k].wasLanding()){
4152                                 if(player[k].isFlip())
4153                                     player[k].jumppower=-4;
4154                                 player[k].targetanimation=player[k].getLanding();
4155                                 emit_sound_at(landsound, player[k].coords, 128.);
4156                                 if(k==0){
4157                                     envsound[numenvsounds]=player[k].coords;
4158                                     envsoundvol[numenvsounds]=16;
4159                                     envsoundlife[numenvsounds]=.4;
4160                                     numenvsounds++;
4161                                 }
4162
4163                             }
4164                         }
4165                     }
4166                 }
4167             }
4168
4169             if(tempcollide&&(/*player[k].jumptogglekeydown*/1==1||player[k].aitype!=playercontrolled))
4170                 for(int l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
4171                     int i=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
4172                     lowpoint=player[k].coords;
4173                     lowpoint.y+=1.35;
4174                     if(objects.type[i]!=rocktype)
4175                         if(player[k].SphereCheck(&lowpoint,1.33,&colpoint,&objects.position[i],&objects.rotation[i],&objects.model[i])!=-1){
4176                             if(player[k].targetanimation!=jumpupanim&&
4177                                     player[k].targetanimation!=jumpdownanim&&
4178                                     player[k].onterrain)
4179                                 player[k].avoidcollided=1;
4180                             player[k].coords=lowpoint;
4181                             player[k].coords.y-=1.35;
4182                             player[k].collide=1;
4183
4184                             if((player[k].grabdelay<=0||player[k].aitype!=playercontrolled)&&
4185                                     (player[k].currentanimation!=climbanim&&
4186                                      player[k].currentanimation!=hanganim&&
4187                                      !player[k].isWallJump()||
4188                                      player[k].targetanimation==jumpupanim||
4189                                      player[k].targetanimation==jumpdownanim)){
4190                                 lowpoint=player[k].coords;
4191                                 objects.model[i].SphereCheckPossible(&lowpoint, 1.5, &objects.position[i], &objects.rotation[i]);
4192                                 lowpoint=player[k].coords;
4193                                 lowpoint.y+=.05;
4194                                 facing=0;
4195                                 facing.z=-1;
4196                                 facing=DoRotation(facing,0,player[k].targetrotation+180,0);
4197                                 lowpointtarget=lowpoint+facing*1.4;
4198                                 whichhit=objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
4199                                 if(whichhit!=-1){
4200                                     lowpoint=player[k].coords;
4201                                     lowpoint.y+=.1;
4202                                     lowpointtarget=lowpoint+facing*1.4;
4203                                     lowpoint2=lowpoint;
4204                                     lowpointtarget2=lowpointtarget;
4205                                     lowpoint3=lowpoint;
4206                                     lowpointtarget3=lowpointtarget;
4207                                     lowpoint4=lowpoint;
4208                                     lowpointtarget4=lowpointtarget;
4209                                     lowpoint5=lowpoint;
4210                                     lowpointtarget5=lowpointtarget;
4211                                     lowpoint6=lowpoint;
4212                                     lowpointtarget6=lowpointtarget;
4213                                     lowpoint7=lowpoint;
4214                                     lowpointtarget7=lowpoint;
4215                                     lowpoint2.x+=.1;
4216                                     lowpointtarget2.x+=.1;
4217                                     lowpoint3.z+=.1;
4218                                     lowpointtarget3.z+=.1;
4219                                     lowpoint4.x-=.1;
4220                                     lowpointtarget4.x-=.1;
4221                                     lowpoint5.z-=.1;
4222                                     lowpointtarget5.z-=.1;
4223                                     lowpoint6.y+=45/13;
4224                                     lowpointtarget6.y+=45/13;
4225                                     lowpointtarget6+=facing*.6;
4226                                     lowpointtarget7.y+=90/13;
4227                                     whichhit=objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
4228                                     if(objects.friction[i]>.5)
4229                                         if(whichhit!=-1){
4230                                             if(whichhit!=-1&&player[k].targetanimation!=jumpupanim&&player[k].targetanimation!=jumpdownanim)
4231                                                 player[k].collided=1;
4232                                             if(checkcollide(lowpoint7,lowpointtarget7)==-1)
4233                                                 if(checkcollide(lowpoint6,lowpointtarget6)==-1)
4234                                                     if(     objects.model[i].LineCheckPossible(&lowpoint2,&lowpointtarget2,
4235                                                                 &colpoint,&objects.position[i],&objects.rotation[i])!=-1&&
4236                                                             objects.model[i].LineCheckPossible(&lowpoint3,&lowpointtarget3,
4237                                                                 &colpoint,&objects.position[i],&objects.rotation[i])!=-1&&
4238                                                             objects.model[i].LineCheckPossible(&lowpoint4,&lowpointtarget4,
4239                                                                 &colpoint,&objects.position[i],&objects.rotation[i])!=-1&&
4240                                                             objects.model[i].LineCheckPossible(&lowpoint5,&lowpointtarget5,
4241                                                                 &colpoint,&objects.position[i],&objects.rotation[i])!=-1)
4242                                                         for(int j=0;j<45;j++){
4243                                                             lowpoint=player[k].coords;
4244                                                             lowpoint.y+=(float)j/13;
4245                                                             lowpointtarget=lowpoint+facing*1.4;
4246                                                             if(objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,
4247                                                                         &colpoint2,&objects.position[i],&objects.rotation[i])==-1){
4248                                                                 if(j<=6||j<=25&&player[k].targetanimation==jumpdownanim)
4249                                                                     break;
4250                                                                 if(player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim){
4251                                                                     lowpoint=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[k],0);
4252                                                                     lowpoint=player[k].coords;
4253                                                                     lowpoint.y+=(float)j/13;
4254                                                                     lowpointtarget=lowpoint+facing*1.3;
4255                                                                     flatfacing=player[k].coords;
4256                                                                     player[k].coords=colpoint-DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[k],0)*.01;
4257                                                                     player[k].coords.y=lowpointtarget.y-.07;
4258                                                                     player[k].currentoffset=(flatfacing-player[k].coords)/player[k].scale;
4259
4260                                                                     if(j>10||!player[k].isRun()){
4261                                                                         if(player[k].targetanimation==jumpdownanim||player[k].targetanimation==jumpupanim){
4262                                                                             if(k==0)
4263                                                                                 pause_sound(whooshsound);
4264                                                                         }
4265                                                                         emit_sound_at(jumpsound, player[k].coords, 128.);
4266
4267                                                                         lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
4268                                                                         player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
4269                                                                         if(lowpointtarget.z<0)
4270                                                                             player[k].rotation=180-player[k].rotation;
4271                                                                         player[k].targetrotation=player[k].rotation;
4272                                                                         player[k].lowrotation=player[k].rotation;
4273
4274                                                                         //player[k].velocity=lowpointtarget*.03;
4275                                                                         player[k].velocity=0;
4276
4277                                                                         //climb ledge (?)
4278                                                                         if(player[k].targetanimation==jumpupanim){
4279                                                                             player[k].targetanimation=climbanim;
4280                                                                             player[k].jumppower=0;
4281                                                                             player[k].jumpclimb=1;
4282                                                                         }
4283                                                                         player[k].transspeed=6;
4284                                                                         player[k].target=0;
4285                                                                         player[k].targetframe=1;
4286                                                                         //hang ledge (?)
4287                                                                         if(j>25){
4288                                                                             setAnimation(k,hanganim);
4289                                                                             player[k].jumppower=0;
4290                                                                         }
4291                                                                     }
4292                                                                     break;
4293                                                                 }
4294                                                             }
4295                                                         }
4296                                         }
4297                                 }
4298                             }
4299                         }
4300                 }
4301             if(player[k].collide<=0){
4302                 //in the air
4303                 if(!player[k].onterrain&&
4304                         player[k].targetanimation!=jumpupanim&&
4305                         player[k].targetanimation!=jumpdownanim&&
4306                         player[k].targetanimation!=climbanim&&
4307                         player[k].targetanimation!=hanganim&&
4308                         !player[k].isWallJump()&&
4309                         !player[k].isFlip()){
4310                     if(player[k].currentanimation!=climbanim&&
4311                             player[k].currentanimation!=tempanim&&
4312                             player[k].targetanimation!=backhandspringanim&&
4313                             (player[k].targetanimation!=rollanim||
4314                              player[k].targetframe<2||
4315                              player[k].targetframe>6)){
4316                         //stagger off ledge (?)
4317                         if(player[k].targetanimation==staggerbackhighanim||player[k].targetanimation==staggerbackhardanim)
4318                             player[k].RagDoll(0);
4319                         setAnimation(k,jumpdownanim);
4320
4321                         if(!k)
4322                           emit_sound_at(whooshsound, player[k].coords, 128.);
4323                     }
4324                     //gravity
4325                     player[k].velocity.y+=gravity;
4326                 }
4327             }
4328         }
4329         player[k].realoldcoords=player[k].coords;
4330     }
4331 }
4332
4333 void Game::doAttacks(){
4334     static XYZ relative;
4335     static int randattack;
4336     static bool playerrealattackkeydown=0;
4337
4338     if(!Input::isKeyDown(attackkey))
4339         oldattackkey=0;
4340     if(oldattackkey)
4341         player[0].attackkeydown=0;
4342     if(oldattackkey)
4343         playerrealattackkeydown=0;
4344     if(!oldattackkey)
4345         playerrealattackkeydown=Input::isKeyDown(attackkey);
4346     if((player[0].parriedrecently<=0||
4347                 player[0].weaponactive==-1)&&
4348             (!oldattackkey||
4349              (realthreat&&
4350               player[0].lastattack!=swordslashanim&&
4351               player[0].lastattack!=knifeslashstartanim&&
4352               player[0].lastattack!=staffhitanim&&
4353               player[0].lastattack!=staffspinhitanim)))
4354         player[0].attackkeydown=Input::isKeyDown(attackkey);
4355     if(Input::isKeyDown(attackkey)&&
4356             !oldattackkey&&
4357             !player[0].backkeydown){
4358         for(int k=0;k<numplayers;k++){
4359             if((player[k].targetanimation==swordslashanim||
4360                         player[k].targetanimation==staffhitanim||
4361                         player[k].targetanimation==staffspinhitanim)&&
4362                     player[0].currentanimation!=dodgebackanim&&
4363                     !player[k].skeleton.free)
4364                 player[k].Reverse();
4365         }
4366     }
4367
4368     if(!hostile||indialogue!=-1)player[0].attackkeydown=0;
4369
4370     for(int k=0;k<numplayers;k++){
4371         if(indialogue!=-1)player[k].attackkeydown=0;
4372         if(player[k].targetanimation!=rabbitrunninganim&&player[k].targetanimation!=wolfrunninganim){
4373             if(player[k].aitype!=playercontrolled)
4374                 player[k].victim=&player[0];
4375             //attack key pressed
4376             if(player[k].attackkeydown){
4377                 //dodge backward
4378                 if(player[k].backkeydown&&
4379                         player[k].targetanimation!=backhandspringanim&&
4380                         (player[k].isIdle()||
4381                          player[k].isStop()||
4382                          player[k].isRun()||
4383                          player[k].targetanimation==walkanim)){
4384                     if(player[k].jumppower<=1){
4385                         player[k].jumppower-=2;
4386                     }else{
4387                         for(int i=0;i<numplayers;i++){
4388                             if(i==k)continue;
4389                             if(player[i].targetanimation==swordslashanim||
4390                                     player[i].targetanimation==knifeslashstartanim||
4391                                     player[i].targetanimation==staffhitanim||
4392                                     player[i].targetanimation==staffspinhitanim)
4393                                 if(findDistancefast(&player[k].coords,&player[i].coords)<6.5&&!player[i].skeleton.free){
4394                                     setAnimation(k,dodgebackanim);
4395                                     player[k].targetrotation=roughDirectionTo(player[k].coords,player[i].coords);
4396                                     player[k].targettilt2=pitchTo(player[k].coords,player[i].coords);
4397                                 }
4398                         }
4399                         if(player[k].targetanimation!=dodgebackanim){
4400                             if(k==0)numflipped++;
4401                             setAnimation(k,backhandspringanim);
4402                             player[k].targetrotation=-rotation+180;
4403                             if(player[k].leftkeydown)
4404                                 player[k].targetrotation-=45;
4405                             if(player[k].rightkeydown)
4406                                 player[k].targetrotation+=45;
4407                             player[k].rotation=player[k].targetrotation;
4408                             player[k].jumppower-=2;
4409                         }
4410                     }
4411                 }
4412                 //attack
4413                 if(!animation[player[k].targetanimation].attack&&
4414                         !player[k].backkeydown&&
4415                         (player[k].isIdle()||
4416                          player[k].isRun()||
4417                          player[k].targetanimation==walkanim||
4418                          player[k].targetanimation==sneakanim||
4419                          player[k].isCrouch())){
4420                     const int attackweapon=player[k].weaponactive==-1?0:weapons.type[player[k].weaponids[player[k].weaponactive]];
4421                     //normal attacks (?)
4422                     player[k].hasvictim=0;
4423                     if(numplayers>1)
4424                         for(int i=0;i<numplayers;i++){
4425                             if(i==k||!(k==0||i==0))continue;
4426                             if(!player[k].hasvictim)
4427                                 if(animation[player[k].targetanimation].attack!=reversal){
4428                                     //choose an attack
4429                                     const float distance=findDistancefast(&player[k].coords,&player[i].coords);
4430                                     if(distance<4.5&&
4431                                             !player[i].skeleton.free&&
4432                                             player[i].howactive<typedead1&&
4433                                             player[i].targetanimation!=jumpreversedanim&&
4434                                             player[i].targetanimation!=rabbitkickreversedanim&&
4435                                             player[i].targetanimation!=rabbitkickanim&&
4436                                             player[k].targetanimation!=rabbitkickanim&&
4437                                             player[i].targetanimation!=getupfrombackanim&&
4438                                             (player[i].targetanimation!=staggerbackhighanim&&
4439                                              (player[i].targetanimation!=staggerbackhardanim||
4440                                               animation[staggerbackhardanim].label[player[i].targetframe]==6))&&
4441                                             player[i].targetanimation!=jumpdownanim&&
4442                                             player[i].targetanimation!=jumpupanim&&
4443                                             player[i].targetanimation!=getupfromfrontanim){
4444                                         player[k].victim=&player[i];
4445                                         player[k].hasvictim=1;
4446                                         if(player[k].aitype==playercontrolled){ //human player
4447                                             //sweep
4448                                             if(distance<2.5*sq(player[k].scale*5)&&
4449                                                     player[k].crouchkeydown&&
4450                                                     animation[player[i].targetanimation].height!=lowheight)
4451                                                 player[k].targetanimation=sweepanim;
4452                                             //winduppunch
4453                                             else if(distance<1.5*sq(player[k].scale*5)&&
4454                                                     animation[player[i].targetanimation].height!=lowheight&&
4455                                                     !player[k].forwardkeydown&&
4456                                                     !player[k].leftkeydown&&
4457                                                     !player[k].rightkeydown&&
4458                                                     !player[k].crouchkeydown&&
4459                                                     !attackweapon&&
4460                                                     !reversaltrain)
4461                                                 player[k].targetanimation=winduppunchanim;
4462                                             //upunch
4463                                             else if(distance<2.5*sq(player[k].scale*5)&&
4464                                                     animation[player[i].targetanimation].height!=lowheight&&
4465                                                     !player[k].forwardkeydown&&
4466                                                     !player[k].leftkeydown&&
4467                                                     !player[k].rightkeydown&&
4468                                                     !player[k].crouchkeydown&&
4469                                                     !attackweapon)
4470                                                 player[k].targetanimation=upunchanim;
4471                                             //knifefollow
4472                                             else if(distance<2.5*sq(player[k].scale*5)&&
4473                                                     player[i].staggerdelay>0&&
4474                                                     attackweapon==knife&&
4475                                                     player[i].bloodloss>player[i].damagetolerance/2)
4476                                                 player[k].targetanimation=knifefollowanim;
4477                                             //knifeslashstart
4478                                             else if(distance<2.5*sq(player[k].scale*5)&&
4479                                                     animation[player[i].targetanimation].height!=lowheight&&
4480                                                     !player[k].forwardkeydown&&
4481                                                     !player[k].leftkeydown&&
4482                                                     !player[k].rightkeydown&&
4483                                                     !player[k].crouchkeydown&&
4484                                                     attackweapon==knife&&
4485                                                     player[k].weaponmissdelay<=0)
4486                                                 player[k].targetanimation=knifeslashstartanim;
4487                                             //swordslash
4488                                             else if(distance<4.5*sq(player[k].scale*5)&&
4489                                                     animation[player[i].targetanimation].height!=lowheight&&
4490                                                     !player[k].crouchkeydown&&
4491                                                     attackweapon==sword&&
4492                                                     player[k].weaponmissdelay<=0)
4493                                                 player[k].targetanimation=swordslashanim;
4494                                             //staffhit
4495                                             else if(distance<4.5*sq(player[k].scale*5)&&
4496                                                     animation[player[i].targetanimation].height!=lowheight&&
4497                                                     !player[k].crouchkeydown&&
4498                                                     attackweapon==staff&&
4499                                                     player[k].weaponmissdelay<=0&&
4500                                                     !player[k].leftkeydown&&
4501                                                     !player[k].rightkeydown&&
4502                                                     !player[k].forwardkeydown)
4503                                                 player[k].targetanimation=staffhitanim;
4504                                             //staffspinhit
4505                                             else if(distance<4.5*sq(player[k].scale*5)&&
4506                                                     animation[player[i].targetanimation].height!=lowheight&&
4507                                                     !player[k].crouchkeydown&&
4508                                                     attackweapon==staff&&
4509                                                     player[k].weaponmissdelay<=0)
4510                                                 player[k].targetanimation=staffspinhitanim;
4511                                             //spinkick
4512                                             else if(distance<2.5*sq(player[k].scale*5)&&
4513                                                     animation[player[i].targetanimation].height!=lowheight)
4514                                                 player[k].targetanimation=spinkickanim;
4515                                             //lowkick
4516                                             else if(distance<2.5*sq(player[k].scale*5)&&
4517                                                     animation[player[i].targetanimation].height==lowheight&&
4518                                                     animation[player[k].targetanimation].attack!=normalattack)
4519                                                 player[k].targetanimation=lowkickanim;
4520                                         } else { //AI player
4521                                             if(distance<4.5*sq(player[k].scale*5)){
4522                                                 randattack=abs(Random()%5);
4523                                                 if(!attackweapon&&distance<2.5*sq(player[k].scale*5)){
4524                                                     //sweep
4525                                                     if(randattack==0&&animation[player[i].targetanimation].height!=lowheight)
4526                                                         player[k].targetanimation=sweepanim;
4527                                                     //upunch
4528                                                     else if(randattack==1&&animation[player[i].targetanimation].height!=lowheight&&
4529                                                             !attackweapon)
4530                                                         player[k].targetanimation=upunchanim;
4531                                                     //spinkick
4532                                                     else if(randattack==2&&animation[player[i].targetanimation].height!=lowheight)
4533                                                         player[k].targetanimation=spinkickanim;
4534                                                     //lowkick
4535                                                     else if(animation[player[i].targetanimation].height==lowheight)
4536                                                         player[k].targetanimation=lowkickanim;
4537                                                 }
4538                                                 if(attackweapon){
4539                                                     //sweep
4540                                                     if((tutoriallevel!=1||!attackweapon)&&
4541                                                             distance<2.5*sq(player[k].scale*5)&&
4542                                                             randattack==0&&
4543                                                             animation[player[i].targetanimation].height!=lowheight)
4544                                                         player[k].targetanimation=sweepanim;
4545                                                     //knifeslashstart
4546                                                     else if(distance<2.5*sq(player[k].scale*5)&&
4547                                                             attackweapon==knife&&
4548                                                             player[k].weaponmissdelay<=0)
4549                                                         player[k].targetanimation=knifeslashstartanim;
4550                                                     //swordslash
4551                                                     else if(!(player[0].victim==&player[i]&&
4552                                                                 player[0].hasvictim&&
4553                                                                 player[0].targetanimation==swordslashanim)&&
4554                                                             attackweapon==sword&&
4555                                                             player[k].weaponmissdelay<=0)
4556                                                         player[k].targetanimation=swordslashanim;
4557                                                     //staffhit
4558                                                     else if(!(player[0].victim==&player[i]&&
4559                                                                 player[0].hasvictim&&
4560                                                                 player[0].targetanimation==swordslashanim)&&
4561                                                             attackweapon==staff&&
4562                                                             player[k].weaponmissdelay<=0&&
4563                                                             randattack<3)
4564                                                         player[k].targetanimation=staffhitanim;
4565                                                     //staffspinhit
4566                                                     else if(!(player[0].victim==&player[i]&&
4567                                                                 player[0].hasvictim&&
4568                                                                 player[0].targetanimation==swordslashanim)&&
4569                                                             attackweapon==staff&&
4570                                                             player[k].weaponmissdelay<=0&&
4571                                                             randattack>=3)
4572                                                         player[k].targetanimation=staffspinhitanim;
4573                                                     //spinkick
4574                                                     else if((tutoriallevel!=1||!attackweapon)&&
4575                                                             distance<2.5*sq(player[k].scale*5)&&
4576                                                             randattack==1&&
4577                                                             animation[player[i].targetanimation].height!=lowheight)
4578                                                         player[k].targetanimation=spinkickanim;
4579                                                     //lowkick
4580                                                     else if(distance<2.5*sq(player[k].scale*5)&&
4581                                                             animation[player[i].targetanimation].height==lowheight&&
4582                                                             animation[player[k].targetanimation].attack!=normalattack)
4583                                                         player[k].targetanimation=lowkickanim;
4584                                                 }
4585                                             }
4586                                         }
4587                                         //upunch becomes wolfslap
4588                                         if(player[k].targetanimation==upunchanim&&player[k].creature==wolftype)
4589                                             player[k].targetanimation=wolfslapanim;
4590                                     }
4591                                     //sneak attacks
4592                                     if((k==0)&&(tutoriallevel!=1||tutorialstage==22)&&
4593                                             player[i].howactive<typedead1&&
4594                                             distance<1.5*sq(player[k].scale*5)&&
4595                                             !player[i].skeleton.free&&
4596                                             player[i].targetanimation!=getupfrombackanim&&
4597                                             player[i].targetanimation!=getupfromfrontanim&&
4598                                             (player[i].stunned>0&&player[k].madskills||
4599                                              player[i].surprised>0||
4600                                              player[i].aitype==passivetype||
4601                                              attackweapon&&player[i].stunned>0)&&
4602                                             normaldotproduct(player[i].facing,player[i].coords-player[k].coords)>0){
4603                                         //sneakattack
4604                                         if(!attackweapon){
4605                                             player[k].currentanimation=sneakattackanim;
4606                                             player[k].targetanimation=sneakattackanim;
4607                                             player[i].currentanimation=sneakattackedanim;
4608                                             player[i].targetanimation=sneakattackedanim;
4609                                             player[k].oldcoords=player[k].coords;
4610                                             player[k].coords=player[i].coords;
4611                                         }
4612                                         //knifesneakattack
4613                                         if(attackweapon==knife){
4614                                             player[k].currentanimation=knifesneakattackanim;
4615                                             player[k].targetanimation=knifesneakattackanim;
4616                                             player[i].currentanimation=knifesneakattackedanim;
4617                                             player[i].targetanimation=knifesneakattackedanim;
4618                                             player[i].oldcoords=player[i].coords;
4619                                             player[i].coords=player[k].coords;
4620                                         }
4621                                         //swordsneakattack
4622                                         if(attackweapon==sword){
4623                                             player[k].currentanimation=swordsneakattackanim;
4624                                             player[k].targetanimation=swordsneakattackanim;
4625                                             player[i].currentanimation=swordsneakattackedanim;
4626                                             player[i].targetanimation=swordsneakattackedanim;
4627                                             player[i].oldcoords=player[i].coords;
4628                                             player[i].coords=player[k].coords;
4629                                         }
4630                                         if(attackweapon!=staff){
4631                                             player[k].victim=&player[i];
4632                                             player[k].hasvictim=1;
4633                                             player[i].targettilt2=0;
4634                                             player[i].targetframe=1;
4635                                             player[i].currentframe=0;
4636                                             player[i].target=0;
4637                                             player[i].velocity=0;
4638                                             player[k].targettilt2=player[i].targettilt2;
4639                                             player[k].currentframe=player[i].currentframe;
4640                                             player[k].targetframe=player[i].targetframe;
4641                                             player[k].target=player[i].target;
4642                                             player[k].velocity=0;
4643                                             player[k].targetrotation=player[i].rotation;
4644                                             player[k].rotation=player[i].rotation;
4645                                             player[i].targetrotation=player[i].rotation;
4646                                         }
4647                                     }
4648                                     if(animation[player[k].targetanimation].attack==normalattack&&
4649                                             player[k].victim==&player[i]&&
4650                                             (!player[i].skeleton.free)){
4651                                         oldattackkey=1;
4652                                         player[k].targetframe=0;
4653                                         player[k].target=0;
4654
4655                                         player[k].targetrotation=roughDirectionTo(player[k].coords,player[i].coords);
4656                                         player[k].targettilt2=pitchTo(player[k].coords,player[i].coords);
4657                                         player[k].lastattack3=player[k].lastattack2;
4658                                         player[k].lastattack2=player[k].lastattack;
4659                                         player[k].lastattack=player[k].targetanimation;
4660                                     }
4661                                     if(player[k].targetanimation==knifefollowanim&&
4662                                             player[k].victim==&player[i]){
4663                                         oldattackkey=1;
4664                                         player[k].targetrotation=roughDirectionTo(player[k].coords,player[i].coords);
4665                                         player[k].targettilt2=pitchTo(player[k].coords,player[i].coords);
4666                                         player[k].victim=&player[i];
4667                                         player[k].hasvictim=1;
4668                                         player[i].targetanimation=knifefollowedanim;
4669                                         player[i].currentanimation=knifefollowedanim;
4670                                         player[i].targettilt2=0;
4671                                         player[i].targettilt2=player[k].targettilt2;
4672                                         player[i].targetframe=1;
4673                                         player[i].currentframe=0;
4674                                         player[i].target=0;
4675                                         player[i].velocity=0;
4676                                         player[k].currentanimation=knifefollowanim;
4677                                         player[k].targetanimation=knifefollowanim;
4678                                         player[k].targettilt2=player[i].targettilt2;
4679                                         player[k].currentframe=player[i].currentframe;
4680                                         player[k].targetframe=player[i].targetframe;
4681                                         player[k].target=player[i].target;
4682                                         player[k].velocity=0;
4683                                         player[k].oldcoords=player[k].coords;
4684                                         player[i].coords=player[k].coords;
4685                                         player[i].targetrotation=player[k].targetrotation;
4686                                         player[i].rotation=player[k].targetrotation;
4687                                         player[k].rotation=player[k].targetrotation;
4688                                         player[i].rotation=player[k].targetrotation;
4689                                     }
4690                                 }
4691                         }
4692                     const bool hasstaff=attackweapon==staff;
4693                     if(k==0&&numplayers>1)
4694                         for(int i=0;i<numplayers;i++){
4695                             if(i==k)continue;
4696                             if((playerrealattackkeydown||player[i].dead||!hasstaff)&&
4697                                     animation[player[k].targetanimation].attack==neutral){
4698                                 const float distance=findDistancefast(&player[k].coords,&player[i].coords);
4699                                 if(!player[i].dead||!realthreat||(!attackweapon&&player[k].crouchkeydown))
4700                                     if(player[i].skeleton.free)
4701                                         if(distance<3.5*sq(player[k].scale*5)&&
4702                                                 (player[i].dead||
4703                                                  player[i].skeleton.longdead>1000||
4704                                                  player[k].isRun()||
4705                                                  hasstaff||
4706                                                  (attackweapon&&
4707                                                   (player[i].skeleton.longdead>2000||
4708                                                    player[i].damage>player[i].damagetolerance/8||
4709                                                    player[i].bloodloss>player[i].damagetolerance/2)&&
4710                                                   distance<1.5*sq(player[k].scale*5)))){
4711                                             player[k].victim=&player[i];
4712                                             player[k].hasvictim=1;
4713                                             if(attackweapon&&tutoriallevel!=1){
4714                                                 //crouchstab
4715                                                 if(player[k].crouchkeydown&&attackweapon==knife&&distance<1.5*sq(player[k].scale*5))
4716                                                     player[k].targetanimation=crouchstabanim;
4717                                                 //swordgroundstab
4718                                                 if(player[k].crouchkeydown&&distance<1.5*sq(player[k].scale*5)&&attackweapon==sword)
4719                                                     player[k].targetanimation=swordgroundstabanim;
4720                                                 //staffgroundsmash
4721                                                 if(distance<3.5*sq(player[k].scale*5)&&attackweapon==staff)
4722                                                     player[k].targetanimation=staffgroundsmashanim;
4723                                             }
4724                                             if(distance<2.5&&
4725                                                     player[k].crouchkeydown&&
4726                                                     player[k].targetanimation!=crouchstabanim&&
4727                                                     !attackweapon&&
4728                                                     player[i].dead&&
4729                                                     player[i].skeleton.free&&
4730                                                     player[i].skeleton.longdead>1000){
4731                                                 player[k].targetanimation=killanim;
4732                                                 //TODO: refactor this out, what does it do?
4733                                                 for(int j=0;j<terrain.numdecals;j++){
4734                                                     if((terrain.decaltype[j]==blooddecal||terrain.decaltype[j]==blooddecalslow)&&
4735                                                             terrain.decalalivetime[j]<2)
4736                                                         terrain.DeleteDecal(j);
4737                                                 }
4738                                                 for(int l=0;l<objects.numobjects;l++){
4739                                                     if(objects.model[l].type==decalstype)
4740                                                         for(int j=0;j<objects.model[l].numdecals;j++){
4741                                                             if((objects.model[l].decaltype[j]==blooddecal||
4742                                                                     objects.model[l].decaltype[j]==blooddecalslow)&&
4743                                                                     objects.model[l].decalalivetime[j]<2)
4744                                                                 objects.model[l].DeleteDecal(j);
4745                                                         }
4746                                                 }
4747                                             }
4748                                             if(!player[i].dead||musictype!=2)
4749                                                 if(distance<3.5&&
4750                                                         (player[k].isRun()||player[k].isIdle()&&player[k].attackkeydown)&&
4751                                                         player[k].staggerdelay<=0&&
4752                                                         (player[i].dead||
4753                                                          player[i].skeleton.longdead<300&&
4754                                                          player[k].lastattack!=spinkickanim&&
4755                                                          player[i].skeleton.free)&&
4756                                                         (!player[i].dead||musictype!=stream_music2)){
4757                                                     player[k].targetanimation=dropkickanim;
4758                                                     for(int j=0;j<terrain.numdecals;j++){
4759                                                         if((terrain.decaltype[j]==blooddecal||terrain.decaltype[j]==blooddecalslow)&&
4760                                                                 terrain.decalalivetime[j]<2){
4761                                                             terrain.DeleteDecal(j);
4762                                                         }
4763                                                     }
4764                                                     for(int l=0;l<objects.numobjects;l++){
4765                                                         if(objects.model[l].type==decalstype)
4766                                                             for(int j=0;j<objects.model[l].numdecals;j++){
4767                                                                 if((objects.model[l].decaltype[j]==blooddecal||
4768                                                                         objects.model[l].decaltype[j]==blooddecalslow)&&
4769                                                                         objects.model[l].decalalivetime[j]<2){
4770                                                                     objects.model[l].DeleteDecal(j);
4771                                                                 }
4772                                                             }
4773                                                     }
4774                                                 }
4775                                         }
4776                                 if(animation[player[k].targetanimation].attack==normalattack&&
4777                                         player[k].victim==&player[i]&&
4778                                         (!player[i].skeleton.free||
4779                                          player[k].targetanimation==killanim||
4780                                          player[k].targetanimation==crouchstabanim||
4781                                          player[k].targetanimation==swordgroundstabanim||
4782                                          player[k].targetanimation==staffgroundsmashanim||
4783                                          player[k].targetanimation==dropkickanim)){
4784                                     oldattackkey=1;
4785                                     player[k].targetframe=0;
4786                                     player[k].target=0;
4787
4788                                     XYZ targetpoint=player[i].coords;
4789                                     if(player[k].targetanimation==crouchstabanim||
4790                                             player[k].targetanimation==swordgroundstabanim||
4791                                             player[k].targetanimation==staffgroundsmashanim){
4792                                         targetpoint+=(playerJoint(i,abdomen).position+
4793                                                  playerJoint(i,neck).position)/2*
4794                                                 player[i].scale;
4795                                     }
4796                                     player[k].targetrotation=roughDirectionTo(player[k].coords,targetpoint);
4797                                     player[k].targettilt2=pitchTo(player[k].coords,targetpoint);
4798
4799                                     if(player[k].targetanimation==crouchstabanim||player[k].targetanimation==swordgroundstabanim){
4800                                         player[k].targetrotation+=(float)(abs(Random()%100)-50)/4;
4801                                     }
4802
4803                                     if(player[k].targetanimation==staffgroundsmashanim)
4804                                         player[k].targettilt2+=10;
4805
4806                                     player[k].lastattack3=player[k].lastattack2;
4807                                     player[k].lastattack2=player[k].lastattack;
4808                                     player[k].lastattack=player[k].targetanimation;
4809
4810                                     if(player[k].targetanimation==swordgroundstabanim){
4811                                         player[k].targetrotation+=30;
4812                                     }
4813                                 }
4814                             }
4815                         }
4816                     if(!player[k].hasvictim){
4817                         //find victim
4818                         for(int i=0;i<numplayers;i++){
4819                             if(i==k||!(i==0||k==0))continue;
4820                             if(!player[i].skeleton.free){
4821                                 if(player[k].hasvictim){
4822                                     if(findDistancefast(&player[k].coords,&player[i].coords)<
4823                                        findDistancefast(&player[k].coords,&player[k].victim->coords))
4824                                         player[k].victim=&player[i];
4825                                 }else{
4826                                     player[k].victim=&player[i];
4827                                     player[k].hasvictim=1;
4828                                 }
4829                             }
4830                         }
4831                     }
4832                     if(player[k].aitype==playercontrolled)
4833                         //rabbit kick
4834                         if(player[k].attackkeydown&&
4835                                 player[k].isRun()&&
4836                                 player[k].wasRun()&&
4837                                 ((player[k].hasvictim&&
4838                                   findDistancefast(&player[k].coords,&player[k].victim->coords)<12*sq(player[k].scale*5)&&
4839                                   findDistancefast(&player[k].coords,&player[k].victim->coords)>7*sq(player[k].scale*5)&&
4840                                   !player[k].victim->skeleton.free&&
4841                                   player[k].victim->targetanimation!=getupfrombackanim&&
4842                                   player[k].victim->targetanimation!=getupfromfrontanim&&
4843                                   animation[player[k].victim->targetanimation].height!=lowheight&&
4844                                   player[k].aitype!=playercontrolled&& //wat???
4845                                   normaldotproduct(player[k].facing,player[k].victim->coords-player[k].coords)>0&&
4846                                   player[k].rabbitkickenabled)||
4847                                  player[k].jumpkeydown)){
4848                             oldattackkey=1;
4849                             setAnimation(k,rabbitkickanim);
4850                         }
4851                     //update counts
4852                     if(animation[player[k].targetanimation].attack&&k==0){
4853                         numattacks++;
4854                         switch(attackweapon){
4855                             case 0: numunarmedattack++; break;
4856                             case knife: numknifeattack++; break;
4857                             case sword: numswordattack++; break;
4858                             case staff: numstaffattack++; break;
4859                         }
4860                     }
4861                 }
4862             }
4863         }
4864     }
4865 }
4866
4867 void Game::doPlayerCollisions(){
4868         static XYZ rotatetarget;
4869     static float collisionradius;
4870     if(numplayers>1)
4871         for(int k=0;k<numplayers;k++)
4872             for(int i=k+1;i<numplayers;i++){
4873                 //neither player is part of a reversal
4874                 if((animation[player[i].targetanimation].attack!=reversed&&
4875                             animation[player[i].targetanimation].attack!=reversal&&
4876                             animation[player[k].targetanimation].attack!=reversed&&
4877                             animation[player[k].targetanimation].attack!=reversal)||(i!=0&&k!=0))
4878                 if((animation[player[i].currentanimation].attack!=reversed&&
4879                             animation[player[i].currentanimation].attack!=reversal&&
4880                             animation[player[k].currentanimation].attack!=reversed&&
4881                             animation[player[k].currentanimation].attack!=reversal)||(i!=0&&k!=0))
4882                 //neither is sleeping
4883                 if(player[i].howactive<=typesleeping&&player[k].howactive<=typesleeping)
4884                 if(player[i].howactive!=typesittingwall&&player[k].howactive!=typesittingwall)
4885                 //in same patch, neither is climbing
4886                 if(player[i].whichpatchx==player[k].whichpatchx&&
4887                         player[i].whichpatchz==player[k].whichpatchz&&
4888                         player[k].skeleton.oldfree==player[k].skeleton.free&&
4889                         player[i].skeleton.oldfree==player[i].skeleton.free&&
4890                         player[i].targetanimation!=climbanim&&
4891                         player[i].targetanimation!=hanganim&&
4892                         player[k].targetanimation!=climbanim&&
4893                         player[k].targetanimation!=hanganim)
4894                 //players are close (bounding box test)
4895                 if(player[i].coords.y>player[k].coords.y-3)
4896                 if(player[i].coords.y<player[k].coords.y+3)
4897                 if(player[i].coords.x>player[k].coords.x-3)
4898                 if(player[i].coords.x<player[k].coords.x+3)
4899                 if(player[i].coords.z>player[k].coords.z-3)
4900                 if(player[i].coords.z<player[k].coords.z+3){
4901                     //spread fire from player to player
4902                     if(findDistancefast(&player[i].coords,&player[k].coords)
4903                             <3*sq((player[i].scale+player[k].scale)*2.5)){
4904                         if(player[i].onfire||player[k].onfire){
4905                             if(!player[i].onfire)player[i].CatchFire();
4906                             if(!player[k].onfire)player[k].CatchFire();
4907                         }
4908                     }
4909
4910                     XYZ tempcoords1=player[i].coords;
4911                     XYZ tempcoords2=player[k].coords;
4912                     if(!player[i].skeleton.oldfree)
4913                         tempcoords1.y+=playerJoint(i,abdomen).position.y*player[i].scale;
4914                     if(!player[k].skeleton.oldfree)
4915                         tempcoords2.y+=playerJoint(k,abdomen).position.y*player[k].scale;
4916                     collisionradius=1.2*sq((player[i].scale+player[k].scale)*2.5);
4917                     if(player[0].hasvictim)
4918                         if(player[0].targetanimation==rabbitkickanim&&(k==0||i==0)&&!player[0].victim->skeleton.free)
4919                             collisionradius=3;
4920                     if((!player[i].skeleton.oldfree||!player[k].skeleton.oldfree)&&
4921                             (findDistancefast(&tempcoords1,&tempcoords2)<collisionradius||
4922                              findDistancefast(&player[i].coords,&player[k].coords)<collisionradius)){
4923                         //jump down on a dead body
4924                         if(k==0||i==0){
4925                             int l=i?i:k;
4926                             if(player[0].targetanimation==jumpdownanim&&
4927                                     !player[0].skeleton.oldfree&&
4928                                     !player[0].skeleton.free&&
4929                                     player[l].skeleton.oldfree&&
4930                                     player[l].skeleton.free&&
4931                                     player[l].dead&&
4932                                     player[0].lastcollide<=0&&
4933                                     fabs(player[l].coords.y-player[0].coords.y)<.2&&
4934                                     findDistancefast(&player[0].coords,&player[l].coords)<.7*sq((player[l].scale+player[0].scale)*2.5)){
4935                                 player[0].coords.y=player[l].coords.y;
4936                                 player[l].velocity=player[0].velocity;
4937                                 player[l].skeleton.free=0;
4938                                 player[l].rotation=0;
4939                                 player[l].RagDoll(0);
4940                                 player[l].DoDamage(20);
4941                                 camerashake+=.3;
4942                                 player[l].skeleton.longdead=0;
4943                                 player[0].lastcollide=1;
4944                             }
4945                         }
4946
4947                         if(     (player[i].skeleton.oldfree==1&&findLengthfast(&player[i].velocity)>1)||
4948                                 (player[k].skeleton.oldfree==1&&findLengthfast(&player[k].velocity)>1)||
4949                                 (player[i].skeleton.oldfree==0&&player[k].skeleton.oldfree==0)){
4950                             rotatetarget=player[k].velocity-player[i].velocity;
4951                             if((player[i].targetanimation!=getupfrombackanim&&player[i].targetanimation!=getupfromfrontanim||
4952                                         player[i].skeleton.free)&&
4953                                     (player[k].targetanimation!=getupfrombackanim&&player[k].targetanimation!=getupfromfrontanim||
4954                                      player[k].skeleton.free))
4955                                 if((((k!=0&&findLengthfast(&rotatetarget)>150||
4956                                                     k==0&&findLengthfast(&rotatetarget)>50&&player[0].rabbitkickragdoll)&&
4957                                                 normaldotproduct(rotatetarget,player[k].coords-player[i].coords)>0)&&
4958                                             (k==0||
4959                                              k!=0&&player[i].skeleton.oldfree==1&&animation[player[k].currentanimation].attack==neutral||
4960                                          /*i!=0&&*/player[k].skeleton.oldfree==1&&animation[player[i].currentanimation].attack==neutral))||
4961                                         (player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip())&&
4962                                         (player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim||player[k].isFlip())&&
4963                                         k==0&&!player[i].skeleton.oldfree&&!player[k].skeleton.oldfree){
4964                                     //If hit by body
4965                                     if(     (i!=0||player[i].skeleton.free)&&
4966                                             (k!=0||player[k].skeleton.free)||
4967                                             (animation[player[i].targetanimation].height==highheight&&
4968                                              animation[player[k].targetanimation].height==highheight)){
4969                                         if(tutoriallevel!=1){
4970                                             emit_sound_at(heavyimpactsound, player[i].coords);
4971                                         }
4972
4973                                         player[i].RagDoll(0);
4974                                         if(player[i].damage>player[i].damagetolerance-findLengthfast(&rotatetarget)/4&&!player[i].dead){
4975                                           award_bonus(0, aimbonus);
4976                                         }
4977                                         player[i].DoDamage(findLengthfast(&rotatetarget)/4);
4978                                         player[k].RagDoll(0);
4979                                         if(player[k].damage>player[k].damagetolerance-findLengthfast(&rotatetarget)/4&&!player[k].dead){
4980                                           award_bonus(0, aimbonus); // Huh, again?
4981                                         }
4982                                         player[k].DoDamage(findLengthfast(&rotatetarget)/4);
4983
4984                                         for(int j=0;j<player[i].skeleton.num_joints;j++){
4985                                             player[i].skeleton.joints[j].velocity=player[i].skeleton.joints[j].velocity/5+player[k].velocity;
4986                                         }
4987                                         for(int j=0;j<player[k].skeleton.num_joints;j++){
4988                                             player[k].skeleton.joints[j].velocity=player[k].skeleton.joints[j].velocity/5+player[i].velocity;
4989                                         }
4990
4991                                     }
4992                                 }
4993                             if(     (animation[player[i].targetanimation].attack==neutral||
4994                                      animation[player[i].targetanimation].attack==normalattack)&&
4995                                     (animation[player[k].targetanimation].attack==neutral||
4996                                      animation[player[k].targetanimation].attack==normalattack)){
4997                                 //If bumped
4998                                 if(player[i].skeleton.oldfree==0&&player[k].skeleton.oldfree==0){
4999                                     if(findDistancefast(&player[k].coords,&player[i].coords)<.5*sq((player[i].scale+player[k].scale)*2.5)){
5000                                         rotatetarget=player[k].coords-player[i].coords;
5001                                         Normalise(&rotatetarget);
5002                                         player[k].coords=(player[k].coords+player[i].coords)/2;
5003                                         player[i].coords=player[k].coords-rotatetarget*fast_sqrt(.6)/2
5004                                             *sq((player[i].scale+player[k].scale)*2.5);
5005                                         player[k].coords+=rotatetarget*fast_sqrt(.6)/2*sq((player[i].scale+player[k].scale)*2.5);
5006                                         if(player[k].howactive==typeactive||hostile)
5007                                             if(player[k].isIdle()){
5008                                                 if(player[k].howactive<typesleeping)
5009                                                     setAnimation(k,player[k].getStop());
5010                                                 else if(player[k].howactive==typesleeping)
5011                                                     setAnimation(k,getupfromfrontanim);
5012                                                 if(!editorenabled)
5013                                                     player[k].howactive=typeactive;
5014                                             }
5015                                         if(player[i].howactive==typeactive||hostile)
5016                                             if(player[i].isIdle()){
5017                                                 if(player[i].howactive<typesleeping)
5018                                                     setAnimation(i,player[k].getStop());
5019                                                 else
5020                                                     setAnimation(i,getupfromfrontanim);
5021                                                 if(!editorenabled)
5022                                                     player[i].howactive=typeactive;
5023                                             }
5024                                     }
5025                                     //jump down on player
5026                                     if(hostile){
5027                                         if(k==0&&i!=0&&player[k].targetanimation==jumpdownanim&&
5028                                                 !player[i].isCrouch()&&
5029                                                 player[i].targetanimation!=rollanim&&
5030                                                 !player[k].skeleton.oldfree&&!
5031                                                 player[k].skeleton.free&&
5032                                                 player[k].lastcollide<=0&&
5033                                                 player[k].velocity.y<-10){
5034                                             player[i].velocity=player[k].velocity;
5035                                             player[k].velocity=player[k].velocity*-.5;
5036                                             player[k].velocity.y=player[i].velocity.y;
5037                                             player[i].DoDamage(20);
5038                                             player[i].RagDoll(0);
5039                                             player[k].lastcollide=1;
5040                                             award_bonus(k, AboveBonus);
5041                                         }
5042                                         if(i==0&&k!=0&&player[i].targetanimation==jumpdownanim&&
5043                                                 !player[k].isCrouch()&&
5044                                                 player[k].targetanimation!=rollanim&&
5045                                                 !player[i].skeleton.oldfree&&
5046                                                 !player[i].skeleton.free&&
5047                                                 player[i].lastcollide<=0&&
5048                                                 player[i].velocity.y<-10){
5049                                             player[k].velocity=player[i].velocity;
5050                                             player[i].velocity=player[i].velocity*-.3;
5051                                             player[i].velocity.y=player[k].velocity.y;
5052                                             player[k].DoDamage(20);
5053                                             player[k].RagDoll(0);
5054                                             player[i].lastcollide=1;
5055                                             award_bonus(i, AboveBonus);
5056                                         }
5057                                     }
5058                                 }
5059                             }
5060                         }
5061                         player[i].CheckKick();
5062                         player[k].CheckKick();
5063                     }
5064                 }
5065             }
5066 }
5067
5068
5069
5070 void Game::doAI(int i){
5071     static bool connected;
5072     if(player[i].aitype!=playercontrolled&&indialogue==-1){
5073         player[i].jumpclimb=0;
5074         //disable movement in editor
5075         if(editorenabled)
5076             player[i].stunned=1;
5077
5078         player[i].pause=0;
5079         if(findDistancefastflat(&player[0].coords,&player[i].coords)<30&&
5080                 player[0].coords.y>player[i].coords.y+2&&
5081                 !player[0].onterrain)
5082             player[i].pause=1;
5083
5084         //pathfinding
5085         if(player[i].aitype==pathfindtype){
5086             if(player[i].finalpathfindpoint==-1){
5087                 float closestdistance;
5088                 float tempdist;
5089                 int closest;
5090                 XYZ colpoint;
5091                 closest=-1;
5092                 closestdistance=-1;
5093                 for(int j=0;j<numpathpoints;j++)
5094                     if(closest==-1||findDistancefast(&player[i].finalfinaltarget,&pathpoint[j])<closestdistance){
5095                         closestdistance=findDistancefast(&player[i].finalfinaltarget,&pathpoint[j]);
5096                         closest=j;
5097                         player[i].finaltarget=pathpoint[j];
5098                     }
5099                 player[i].finalpathfindpoint=closest;
5100                 for(int j=0;j<numpathpoints;j++)
5101                     for(int k=0;k<numpathpointconnect[j];k++){
5102                         DistancePointLine(&player[i].finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist,&colpoint );
5103                         if(sq(tempdist)<closestdistance)
5104                             if(findDistance(&colpoint,&pathpoint[j])+findDistance(&colpoint,&pathpoint[pathpointconnect[j][k]])<
5105                                     findDistance(&pathpoint[j],&pathpoint[pathpointconnect[j][k]])+.1){
5106                                 closestdistance=sq(tempdist);
5107                                 closest=j;
5108                                 player[i].finaltarget=colpoint;
5109                             }
5110                     }
5111                 player[i].finalpathfindpoint=closest;
5112
5113             }
5114             if(player[i].targetpathfindpoint==-1){
5115                 float closestdistance;
5116                 float tempdist;
5117                 int closest;
5118                 XYZ colpoint;
5119                 closest=-1;
5120                 closestdistance=-1;
5121                 if(player[i].lastpathfindpoint==-1){
5122                     for(int j=0;j<numpathpoints;j++){
5123                         if(j!=player[i].lastpathfindpoint)
5124                             if(closest==-1||(findDistancefast(&player[i].coords,&pathpoint[j])<closestdistance)){
5125                                 closestdistance=findDistancefast(&player[i].coords,&pathpoint[j]);
5126                                 closest=j;
5127                             }
5128                     }
5129                     player[i].targetpathfindpoint=closest;
5130                     for(int j=0;j<numpathpoints;j++)
5131                         if(j!=player[i].lastpathfindpoint)
5132                             for(int k=0;k<numpathpointconnect[j];k++){
5133                                 DistancePointLine(&player[i].coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist,&colpoint );
5134                                 if(sq(tempdist)<closestdistance){
5135                                     if(findDistance(&colpoint,&pathpoint[j])+findDistance(&colpoint,&pathpoint[pathpointconnect[j][k]])<
5136                                             findDistance(&pathpoint[j],&pathpoint[pathpointconnect[j][k]])+.1){
5137                                         closestdistance=sq(tempdist);
5138                                         closest=j;
5139                                     }
5140                                 }
5141                             }
5142                     player[i].targetpathfindpoint=closest;
5143                 }
5144                 else
5145                 {
5146                     for(int j=0;j<numpathpoints;j++)
5147                         if(j!=player[i].lastpathfindpoint&&
5148                                 j!=player[i].lastpathfindpoint2&&
5149                                 j!=player[i].lastpathfindpoint3&&
5150                                 j!=player[i].lastpathfindpoint4){
5151                             connected=0;
5152                             if(numpathpointconnect[j])
5153                                 for(int k=0;k<numpathpointconnect[j];k++)
5154                                     if(pathpointconnect[j][k]==player[i].lastpathfindpoint)
5155                                         connected=1;
5156                             if(!connected)
5157                                 if(numpathpointconnect[player[i].lastpathfindpoint])
5158                                     for(int k=0;k<numpathpointconnect[player[i].lastpathfindpoint];k++)
5159                                         if(pathpointconnect[player[i].lastpathfindpoint][k]==j)
5160                                             connected=1;
5161                             if(connected){
5162                                 tempdist=findPathDist(j,player[i].finalpathfindpoint);
5163                                 if(closest==-1||tempdist<closestdistance){
5164                                     closestdistance=tempdist;
5165                                     closest=j;
5166                                 }
5167                             }
5168                         }
5169                     player[i].targetpathfindpoint=closest;
5170                 }
5171             }
5172             player[i].losupdatedelay-=multiplier;
5173
5174             player[i].targetrotation=roughDirectionTo(player[i].coords,pathpoint[player[i].targetpathfindpoint]);
5175             player[i].lookrotation=player[i].targetrotation;
5176
5177             //reached target point
5178             if(findDistancefastflat(&player[i].coords,&pathpoint[player[i].targetpathfindpoint])<.6){
5179                 player[i].lastpathfindpoint4=player[i].lastpathfindpoint3;
5180                 player[i].lastpathfindpoint3=player[i].lastpathfindpoint2;
5181                 player[i].lastpathfindpoint2=player[i].lastpathfindpoint;
5182                 player[i].lastpathfindpoint=player[i].targetpathfindpoint;
5183                 if(player[i].lastpathfindpoint2==-1)
5184                     player[i].lastpathfindpoint2=player[i].lastpathfindpoint;
5185                 if(player[i].lastpathfindpoint3==-1)
5186                     player[i].lastpathfindpoint3=player[i].lastpathfindpoint2;
5187                 if(player[i].lastpathfindpoint4==-1)
5188                     player[i].lastpathfindpoint4=player[i].lastpathfindpoint3;
5189                 player[i].targetpathfindpoint=-1;
5190             }
5191             if(     findDistancefastflat(&player[i].coords,&player[i].finalfinaltarget)<
5192                     findDistancefastflat(&player[i].coords,&player[i].finaltarget)||
5193                     findDistancefastflat(&player[i].coords,&player[i].finaltarget)<.6*sq(player[i].scale*5)||
5194                     player[i].lastpathfindpoint==player[i].finalpathfindpoint){
5195                 player[i].aitype=passivetype;
5196             }
5197
5198             player[i].forwardkeydown=1;
5199             player[i].leftkeydown=0;
5200             player[i].backkeydown=0;
5201             player[i].rightkeydown=0;
5202             player[i].crouchkeydown=0;
5203             player[i].attackkeydown=0;
5204             player[i].throwkeydown=0;
5205
5206             if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8)
5207                 player[i].targetrotation+=90*(player[i].whichdirection*2-1);
5208
5209             if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
5210                 player[i].jumpkeydown=0;
5211             if((player[i].collided>.8&&player[i].jumppower>=5))
5212                 player[i].jumpkeydown=1;
5213
5214             if((tutoriallevel!=1||cananger)&&
5215                     hostile&&
5216                     !player[0].dead&&
5217                     findDistancefast(&player[i].coords,&player[0].coords)<400&&
5218                     player[i].occluded<25){
5219                 if(findDistancefast(&player[i].coords,&player[0].coords)<12&&
5220                         animation[player[0].targetanimation].height!=lowheight&&
5221                         !editorenabled&&
5222                         (player[0].coords.y<player[i].coords.y+5||player[0].onterrain))
5223                     player[i].aitype=attacktypecutoff;
5224                 if(findDistancefast(&player[i].coords,&player[0].coords)<30&&
5225                         animation[player[0].targetanimation].height==highheight&&
5226                         !editorenabled)
5227                     player[i].aitype=attacktypecutoff;
5228
5229                 if(player[i].losupdatedelay<0&&!editorenabled&&player[i].occluded<2){
5230                     player[i].losupdatedelay=.2;
5231                     for(int j=0;j<numplayers;j++)
5232                         if(j==0||player[j].skeleton.free||player[j].aitype!=passivetype)
5233                             if(abs(Random()%2)||animation[player[j].targetanimation].height!=lowheight||j!=0)
5234                                 if(findDistancefast(&player[i].coords,&player[j].coords)<400)
5235                                     if(normaldotproduct(player[i].facing,player[j].coords-player[i].coords)>0)
5236                                         if(player[j].coords.y<player[i].coords.y+5||player[j].onterrain)
5237                                             if(!player[j].isWallJump()&&-1==checkcollide(
5238                                                             DoRotation(playerJoint(i,head).position,0,player[i].rotation,0)
5239                                                                 *player[i].scale+player[i].coords,
5240                                                             DoRotation(playerJoint(j,head).position,0,player[j].rotation,0)
5241                                                                 *player[j].scale+player[j].coords)||
5242                                                     (player[j].targetanimation==hanganim&&
5243                                                      normaldotproduct(player[j].facing,player[i].coords-player[j].coords)<0)){
5244                                                 player[i].aitype=searchtype;
5245                                                 player[i].lastchecktime=12;
5246                                                 player[i].lastseen=player[j].coords;
5247                                                 player[i].lastseentime=12;
5248                                             }
5249                 }
5250             }
5251             if(player[i].aitype==attacktypecutoff&&musictype!=2)
5252                 if(player[i].creature!=wolftype){
5253                     player[i].stunned=.6;
5254                     player[i].surprised=.6;
5255                 }
5256         }
5257
5258         if(player[i].aitype!=passivetype&&leveltime>.5)
5259             player[i].howactive=typeactive;
5260
5261         if(player[i].aitype==passivetype){
5262             player[i].aiupdatedelay-=multiplier;
5263             player[i].losupdatedelay-=multiplier;
5264             player[i].lastseentime+=multiplier;
5265             player[i].pausetime-=multiplier;
5266             if(player[i].lastseentime>1)
5267                 player[i].lastseentime=1;
5268
5269             if(player[i].aiupdatedelay<0){
5270                 if(player[i].numwaypoints>1&&player[i].howactive==typeactive&&player[i].pausetime<=0){
5271                     player[i].targetrotation=roughDirectionTo(player[i].coords,player[i].waypoints[player[i].waypoint]);
5272                     player[i].lookrotation=player[i].targetrotation;
5273                     player[i].aiupdatedelay=.05;
5274
5275                     if(findDistancefastflat(&player[i].coords,&player[i].waypoints[player[i].waypoint])<1){
5276                         if(player[i].waypointtype[player[i].waypoint]==wppause)
5277                             player[i].pausetime=4;
5278                         player[i].waypoint++;
5279                         if(player[i].waypoint>player[i].numwaypoints-1)
5280                             player[i].waypoint=0;
5281
5282                     }
5283                 }
5284
5285                 if(player[i].numwaypoints>1&&player[i].howactive==typeactive&&player[i].pausetime<=0)
5286                     player[i].forwardkeydown=1;
5287                 else
5288                     player[i].forwardkeydown=0;
5289                 player[i].leftkeydown=0;
5290                 player[i].backkeydown=0;
5291                 player[i].rightkeydown=0;
5292                 player[i].crouchkeydown=0;
5293                 player[i].attackkeydown=0;
5294                 player[i].throwkeydown=0;
5295
5296                 if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
5297                     if(!player[i].avoidsomething)
5298                         player[i].targetrotation+=90*(player[i].whichdirection*2-1);
5299                     else{
5300                         XYZ leftpos,rightpos;
5301                         float leftdist,rightdist;
5302                         leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
5303                         rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
5304                         leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
5305                         rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
5306                         if(leftdist<rightdist)
5307                             player[i].targetrotation+=90;
5308                         else
5309                             player[i].targetrotation-=90;
5310                     }
5311                 }
5312             }
5313             if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
5314                 player[i].jumpkeydown=0;
5315             if((player[i].collided>.8&&player[i].jumppower>=5))
5316                 player[i].jumpkeydown=1;
5317
5318
5319             //hearing sounds
5320             if(!editorenabled){
5321                 if(player[i].howactive<=typesleeping)
5322                     if(numenvsounds>0&&(tutoriallevel!=1||cananger)&&hostile)
5323                         for(int j=0;j<numenvsounds;j++){
5324                             float vol=player[i].howactive==typesleeping?envsoundvol[j]-14:envsoundvol[j];
5325                             if(vol>0&&findDistancefast(&player[i].coords,&envsound[j])<
5326                                     2*(vol+vol*(player[i].creature==rabbittype)*3))
5327                                 player[i].aitype=attacktypecutoff;
5328                         }
5329
5330                 if(player[i].aitype!=passivetype){
5331                     if(player[i].howactive==typesleeping)
5332                         setAnimation(i,getupfromfrontanim);
5333                     player[i].howactive=typeactive;
5334                 }
5335             }
5336
5337             if(player[i].howactive<typesleeping&&
5338                     ((tutoriallevel!=1||cananger)&&hostile)&&
5339                     !player[0].dead&&
5340                     findDistancefast(&player[i].coords,&player[0].coords)<400&&
5341                     player[i].occluded<25){
5342                 if(findDistancefast(&player[i].coords,&player[0].coords)<12&&
5343                         animation[player[0].targetanimation].height!=lowheight&&!editorenabled)
5344                     player[i].aitype=attacktypecutoff;
5345                 if(findDistancefast(&player[i].coords,&player[0].coords)<30&&
5346                         animation[player[0].targetanimation].height==highheight&&!editorenabled)
5347                     player[i].aitype=attacktypecutoff;
5348
5349                 //wolf smell
5350                 if(player[i].creature==wolftype){
5351                     XYZ windsmell;
5352                     for(int j=0;j<numplayers;j++){
5353                         if(j==0||(player[j].dead&&player[j].bloodloss>0)){
5354                             float smelldistance=50;
5355                             if(j==0&&player[j].num_weapons>0){
5356                                 if(weapons.bloody[player[j].weaponids[0]])
5357                                     smelldistance=100;
5358                                 if(player[j].num_weapons==2)
5359                                     if(weapons.bloody[player[j].weaponids[1]])
5360                                         smelldistance=100;
5361                             }
5362                             if(j!=0)
5363                                 smelldistance=100;
5364                             windsmell=windvector;
5365                             Normalise(&windsmell);
5366                             windsmell=windsmell*2+player[j].coords;
5367                             if(findDistancefast(&player[i].coords,&windsmell)<smelldistance&&!editorenabled)
5368                                 player[i].aitype=attacktypecutoff;
5369                         }
5370                     }
5371                 }
5372
5373                 if(player[i].howactive<typesleeping&&player[i].losupdatedelay<0&&!editorenabled&&player[i].occluded<2){
5374                     player[i].losupdatedelay=.2;
5375                     for(int j=0;j<numplayers;j++){
5376                         if(j==0||player[j].skeleton.free||player[j].aitype!=passivetype){
5377                             if(abs(Random()%2)||animation[player[j].targetanimation].height!=lowheight||j!=0)
5378                                 if(findDistancefast(&player[i].coords,&player[j].coords)<400)
5379                                     if(normaldotproduct(player[i].facing,player[j].coords-player[i].coords)>0)
5380                                         if((-1==checkcollide(
5381                                                         DoRotation(playerJoint(i,head).position,0,player[i].rotation,0)*
5382                                                             player[i].scale+player[i].coords,
5383                                                         DoRotation(playerJoint(j,head).position,0,player[j].rotation,0)*
5384                                                             player[j].scale+player[j].coords)&&
5385                                                     !player[j].isWallJump())||
5386                                                 (player[j].targetanimation==hanganim&&
5387                                                  normaldotproduct(player[j].facing,player[i].coords-player[j].coords)<0)){
5388                                             player[i].lastseentime-=.2;
5389                                             if(j==0&&animation[player[j].targetanimation].height==lowheight)
5390                                                 player[i].lastseentime-=.4;
5391                                             else
5392                                                 player[i].lastseentime-=.6;
5393                                         }
5394                             if(player[i].lastseentime<=0){
5395                                 player[i].aitype=searchtype;
5396                                 player[i].lastchecktime=12;
5397                                 player[i].lastseen=player[j].coords;
5398                                 player[i].lastseentime=12;
5399                             }
5400                         }
5401                     }
5402                 }
5403             }
5404             //alerted surprise
5405             if(player[i].aitype==attacktypecutoff&&musictype!=2){
5406                 if(player[i].creature!=wolftype){
5407                     player[i].stunned=.6;
5408                     player[i].surprised=.6;
5409                 }
5410                 if(player[i].creature==wolftype){
5411                     player[i].stunned=.47;
5412                     player[i].surprised=.47;
5413                 }
5414                 numseen++;
5415             }
5416         }
5417
5418         //search for player
5419         int j;
5420         if(player[i].aitype==searchtype){
5421             player[i].aiupdatedelay-=multiplier;
5422             player[i].losupdatedelay-=multiplier;
5423             if(!player[i].pause)
5424                 player[i].lastseentime-=multiplier;
5425             player[i].lastchecktime-=multiplier;
5426
5427             if(player[i].isRun()&&!player[i].onground){
5428                 if(player[i].coords.y>terrain.getHeight(player[i].coords.x,player[i].coords.z)+10){
5429                     XYZ test2=player[i].coords+player[i].facing;
5430                     test2.y+=5;
5431                     XYZ test=player[i].coords+player[i].facing;
5432                     test.y-=10;
5433                     j=checkcollide(test2,test,player[i].laststanding);
5434                     if(j==-1)
5435                         j=checkcollide(test2,test);
5436                     if(j==-1){
5437                         player[i].velocity=0;
5438                         setAnimation(i,player[i].getStop());
5439                         player[i].targetrotation+=180;
5440                         player[i].stunned=.5;
5441                         //player[i].aitype=passivetype;
5442                         player[i].aitype=pathfindtype;
5443                         player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
5444                         player[i].finalpathfindpoint=-1;
5445                         player[i].targetpathfindpoint=-1;
5446                         player[i].lastpathfindpoint=-1;
5447                         player[i].lastpathfindpoint2=-1;
5448                         player[i].lastpathfindpoint3=-1;
5449                         player[i].lastpathfindpoint4=-1;
5450                     }
5451                     else player[i].laststanding=j;
5452                 }
5453             }
5454             //check out last seen location
5455             if(player[i].aiupdatedelay<0){
5456                 player[i].targetrotation=roughDirectionTo(player[i].coords,player[i].lastseen);
5457                 player[i].lookrotation=player[i].targetrotation;
5458                 player[i].aiupdatedelay=.05;
5459                 player[i].forwardkeydown=1;
5460
5461                 if(findDistancefastflat(&player[i].coords,&player[i].lastseen)<1*sq(player[i].scale*5)||player[i].lastchecktime<0){
5462                     player[i].forwardkeydown=0;
5463                     player[i].aiupdatedelay=1;
5464                     player[i].lastseen.x+=(float(Random()%100)-50)/25;
5465                     player[i].lastseen.z+=(float(Random()%100)-50)/25;
5466                     player[i].lastchecktime=3;
5467                 }
5468
5469                 player[i].leftkeydown=0;
5470                 player[i].backkeydown=0;
5471                 player[i].rightkeydown=0;
5472                 player[i].crouchkeydown=0;
5473                 player[i].attackkeydown=0;
5474                 player[i].throwkeydown=0;
5475
5476                 if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
5477                     if(!player[i].avoidsomething)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
5478                     else{
5479                         XYZ leftpos,rightpos;
5480                         float leftdist,rightdist;
5481                         leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
5482                         rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
5483                         leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
5484                         rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
5485                         if(leftdist<rightdist)player[i].targetrotation+=90;
5486                         else player[i].targetrotation-=90;
5487                     }
5488                 }
5489             }
5490             if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
5491                 player[i].jumpkeydown=0;
5492             if((player[i].collided>.8&&player[i].jumppower>=5))
5493                 player[i].jumpkeydown=1;
5494
5495             if(numenvsounds>0&&((tutoriallevel!=1||cananger)&&hostile))
5496                 for(int k=0;k<numenvsounds;k++){
5497                     if(findDistancefast(&player[i].coords,&envsound[k])<2*(envsoundvol[k]+envsoundvol[k]*(player[i].creature==rabbittype)*3)){
5498                         player[i].aitype=attacktypecutoff;
5499                     }
5500                 }
5501
5502             if(!player[0].dead&&
5503                     player[i].losupdatedelay<0&&
5504                     !editorenabled&&
5505                     player[i].occluded<2&&
5506                     ((tutoriallevel!=1||cananger)&&hostile)){
5507                 player[i].losupdatedelay=.2;
5508                 if(findDistancefast(&player[i].coords,&player[0].coords)<4&&animation[player[i].targetanimation].height!=lowheight){
5509                     player[i].aitype=attacktypecutoff;
5510                     player[i].lastseentime=1;
5511                 }
5512                 if(abs(Random()%2)||animation[player[i].targetanimation].height!=lowheight)
5513                     //TODO: factor out canSeePlayer()
5514                     if(findDistancefast(&player[i].coords,&player[0].coords)<400)
5515                         if(normaldotproduct(player[i].facing,player[0].coords-player[i].coords)>0)
5516                             if((checkcollide(
5517                                         DoRotation(playerJoint(i,head).position,0,player[i].rotation,0)*
5518                                             player[i].scale+player[i].coords,
5519                                         DoRotation(playerJoint(0,head).position,0,player[0].rotation,0)*
5520                                             player[0].scale+player[0].coords)==-1)||
5521                                     (player[0].targetanimation==hanganim&&normaldotproduct(
5522                                         player[0].facing,player[i].coords-player[0].coords)<0)){
5523                                     /* //TODO: changed j to 0 on a whim, make sure this is correct
5524                                     (player[j].targetanimation==hanganim&&normaldotproduct(
5525                                         player[j].facing,player[i].coords-player[j].coords)<0)
5526                                     */
5527                                 player[i].aitype=attacktypecutoff;
5528                                 player[i].lastseentime=1;
5529                             }
5530             }
5531             //player escaped
5532             if(player[i].lastseentime<0){
5533                 //player[i].aitype=passivetype;
5534                 numescaped++;
5535                 player[i].aitype=pathfindtype;
5536                 player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
5537                 player[i].finalpathfindpoint=-1;
5538                 player[i].targetpathfindpoint=-1;
5539                 player[i].lastpathfindpoint=-1;
5540                 player[i].lastpathfindpoint2=-1;
5541                 player[i].lastpathfindpoint3=-1;
5542                 player[i].lastpathfindpoint4=-1;
5543             }
5544         }
5545
5546         if(player[i].aitype!=gethelptype)
5547             player[i].runninghowlong=0;
5548
5549         //get help from buddies
5550         if(player[i].aitype==gethelptype){
5551             player[i].runninghowlong+=multiplier;
5552             player[i].aiupdatedelay-=multiplier;
5553
5554             if(player[i].aiupdatedelay<0||player[i].ally==0){
5555                 player[i].aiupdatedelay=.2;
5556
5557                 //find closest ally
5558                 //TODO: factor out closest search somehow
5559                 if(!player[i].ally){
5560                     int closest=-1;
5561                     float closestdist=-1;
5562                     for(int k=0;k<numplayers;k++){
5563                         if(k!=i&&k!=0&&!player[k].dead&&
5564                                 player[k].howactive<typedead1&&
5565                                 !player[k].skeleton.free&&
5566                                 player[k].aitype==passivetype){
5567                             float distance=findDistancefast(&player[i].coords,&player[k].coords);
5568                             if(closestdist==-1||distance<closestdist){
5569                                 closestdist=distance;
5570                                 closest=k;
5571                             }
5572                             closest=k;
5573                         }
5574                     }
5575                     if(closest!=-1)
5576                         player[i].ally=closest;
5577                     else
5578                         player[i].ally=0;
5579                     player[i].lastseen=player[0].coords;
5580                     player[i].lastseentime=12;
5581                 }
5582
5583
5584                 player[i].lastchecktime=12;
5585
5586                 XYZ facing=player[i].coords;
5587                 XYZ flatfacing=player[player[i].ally].coords;
5588                 facing.y+=playerJoint(i,head).position.y*player[i].scale;
5589                 flatfacing.y+=playerJoint(player[i].ally,head).position.y*player[player[i].ally].scale;
5590                 if(-1!=checkcollide(facing,flatfacing))
5591                     player[i].lastseentime-=.1;
5592
5593                 //no available ally, run back to player
5594                 if(player[i].ally<=0||
5595                         player[player[i].ally].skeleton.free||
5596                         player[player[i].ally].aitype!=passivetype||
5597                         player[i].lastseentime<=0){
5598                     player[i].aitype=searchtype;
5599                     player[i].lastseentime=12;
5600                 }
5601
5602                 //seek out ally
5603                 if(player[i].ally>0){
5604                     player[i].targetrotation=roughDirectionTo(player[i].coords,player[player[i].ally].coords);
5605                     player[i].lookrotation=player[i].targetrotation;
5606                     player[i].aiupdatedelay=.05;
5607                     player[i].forwardkeydown=1;
5608
5609                     if(findDistancefastflat(&player[i].coords,&player[player[i].ally].coords)<3){
5610                         player[i].aitype=searchtype;
5611                         player[i].lastseentime=12;
5612                         player[player[i].ally].aitype=searchtype;
5613                         if(player[player[i].ally].lastseentime<player[i].lastseentime){
5614                             player[player[i].ally].lastseen=player[i].lastseen;
5615                             player[player[i].ally].lastseentime=player[i].lastseentime;
5616                             player[player[i].ally].lastchecktime=player[i].lastchecktime;
5617                         }
5618                     }
5619
5620                     if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
5621                         if(!player[i].avoidsomething)
5622                             player[i].targetrotation+=90*(player[i].whichdirection*2-1);
5623                         else{
5624                             XYZ leftpos,rightpos;
5625                             float leftdist,rightdist;
5626                             leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
5627                             rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
5628                             leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
5629                             rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
5630                             if(leftdist<rightdist)
5631                                 player[i].targetrotation+=90;
5632                             else
5633                                 player[i].targetrotation-=90;
5634                         }
5635                     }
5636                 }
5637
5638                 player[i].leftkeydown=0;
5639                 player[i].backkeydown=0;
5640                 player[i].rightkeydown=0;
5641                 player[i].crouchkeydown=0;
5642                 player[i].attackkeydown=0;
5643             }
5644             if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
5645                 player[i].jumpkeydown=0;
5646             if(player[i].collided>.8&&player[i].jumppower>=5)
5647                 player[i].jumpkeydown=1;
5648         }
5649
5650         //retreiving a weapon on the ground
5651         if(player[i].aitype==getweapontype){
5652             player[i].aiupdatedelay-=multiplier;
5653             player[i].lastchecktime-=multiplier;
5654
5655             if(player[i].aiupdatedelay<0){
5656                 player[i].aiupdatedelay=.2;
5657
5658                 //ALLY IS WEPON
5659                 if(player[i].ally<0){
5660                     int closest=-1;
5661                     float closestdist=-1;
5662                     for(int k=0;k<weapons.numweapons;k++)
5663                         if(weapons.owner[k]==-1){
5664                             float distance=findDistancefast(&player[i].coords,&weapons.position[k]);
5665                             if(closestdist==-1||distance<closestdist){
5666                                 closestdist=distance;
5667                                 closest=k;
5668                             }
5669                             closest=k;
5670                         }
5671                     if(closest!=-1)
5672                         player[i].ally=closest;
5673                     else
5674                         player[i].ally=-1;
5675                 }
5676
5677                 player[i].lastseentime=12;
5678
5679                 if(!player[0].dead&&((tutoriallevel!=1||cananger)&&hostile))
5680                     if(player[i].ally<0||player[i].weaponactive!=-1||player[i].lastchecktime<=0){
5681                         player[i].aitype=attacktypecutoff;
5682                         player[i].lastseentime=1;
5683                     }
5684                 if(!player[0].dead)
5685                     if(player[i].ally>=0){
5686                         if(weapons.owner[player[i].ally]!=-1||
5687                                 findDistancefast(&player[i].coords,&weapons.position[player[i].ally])>16){
5688                             player[i].aitype=attacktypecutoff;
5689                             player[i].lastseentime=1;
5690                         }
5691                         //TODO: factor these out as moveToward()
5692                         player[i].targetrotation=roughDirectionTo(player[i].coords,weapons.position[player[i].ally]);
5693                         player[i].lookrotation=player[i].targetrotation;
5694                         player[i].aiupdatedelay=.05;
5695                         player[i].forwardkeydown=1;
5696
5697
5698                         if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
5699                             if(!player[i].avoidsomething)
5700                                 player[i].targetrotation+=90*(player[i].whichdirection*2-1);
5701                             else{
5702                                 XYZ leftpos,rightpos;
5703                                 float leftdist,rightdist;
5704                                 leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
5705                                 rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
5706                                 leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
5707                                 rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
5708                                 if(leftdist<rightdist)
5709                                     player[i].targetrotation+=90;
5710                                 else
5711                                     player[i].targetrotation-=90;
5712                             }
5713                         }
5714                     }
5715
5716                 player[i].leftkeydown=0;
5717                 player[i].backkeydown=0;
5718                 player[i].rightkeydown=0;
5719                 player[i].attackkeydown=0;
5720                 player[i].throwkeydown=1;
5721                 player[i].crouchkeydown=0;
5722                 if(player[i].targetanimation!=crouchremoveknifeanim&&
5723                         player[i].targetanimation!=removeknifeanim)
5724                     player[i].throwtogglekeydown=0;
5725                 player[i].drawkeydown=0;
5726             }
5727             if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
5728                 player[i].jumpkeydown=0;
5729             if((player[i].collided>.8&&player[i].jumppower>=5))
5730                 player[i].jumpkeydown=1;
5731         }
5732
5733         if(player[i].aitype==attacktypecutoff){
5734             player[i].aiupdatedelay-=multiplier;
5735             //dodge or reverse rabbit kicks, knife throws, flips
5736             if(player[i].damage<player[i].damagetolerance*2/3)
5737                 if((player[0].targetanimation==rabbitkickanim||
5738                             player[0].targetanimation==knifethrowanim||
5739                             (player[0].isFlip()&&
5740                              normaldotproduct(player[0].facing,player[0].coords-player[i].coords)<0))&&
5741                         !player[0].skeleton.free&&
5742                         (player[i].aiupdatedelay<.1)){
5743                     player[i].attackkeydown=0;
5744                     if(player[i].isIdle())
5745                         player[i].crouchkeydown=1;
5746                     if(player[0].targetanimation!=rabbitkickanim&&player[0].weaponactive!=-1){
5747                         if(weapons.type[player[0].weaponids[0]]==knife){
5748                             if(player[i].isIdle()||player[i].isCrouch()||player[i].isRun()||player[i].isFlip()){
5749                                 if(abs(Random()%2==0))
5750                                     setAnimation(i,backhandspringanim);
5751                                 else
5752                                     setAnimation(i,rollanim);
5753                                 player[i].targetrotation+=90*(abs(Random()%2)*2-1);
5754                                 player[i].wentforweapon=0;
5755                             }
5756                             if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim)
5757                                 setAnimation(i,flipanim);
5758                         }
5759                     }
5760                     player[i].forwardkeydown=0;
5761                     player[i].aiupdatedelay=.02;
5762                 }
5763             //get confused by flips
5764             if(player[0].isFlip()&&
5765                     !player[0].skeleton.free&&
5766                     player[0].targetanimation!=walljumprightkickanim&&
5767                     player[0].targetanimation!=walljumpleftkickanim){
5768                 if(findDistancefast(&player[0].coords,&player[i].coords)<25)
5769                     if((1-player[i].damage/player[i].damagetolerance)>.5)
5770                         player[i].stunned=1;
5771             }
5772             //go for weapon on the ground
5773             if(player[i].wentforweapon<3)
5774                 for(int k=0;k<weapons.numweapons;k++)
5775                     if(player[i].creature!=wolftype)
5776                         if(player[i].num_weapons==0&&
5777                                 weapons.owner[k]==-1&&
5778                                 weapons.velocity[i].x==0&&
5779                                 weapons.velocity[i].z==0&&
5780                                 weapons.velocity[i].y==0){
5781                             if(findDistancefast(&player[i].coords,&weapons.position[k])<16){
5782                                 player[i].wentforweapon++;
5783                                 player[i].lastchecktime=6;
5784                                 player[i].aitype=getweapontype;
5785                                 player[i].ally=-1;
5786                             }
5787                         }
5788             //dodge/reverse walljump kicks
5789             if(player[i].damage<player[i].damagetolerance/2)
5790                 if(animation[player[i].targetanimation].height!=highheight)
5791                     if(player[i].damage<player[i].damagetolerance*.5&&
5792                             ((player[0].targetanimation==walljumprightkickanim||
5793                               player[0].targetanimation==walljumpleftkickanim)&&
5794                              ((player[i].aiupdatedelay<.15&&
5795                                difficulty==2)||
5796                               (player[i].aiupdatedelay<.08&&
5797                                difficulty!=2)))){
5798                         player[i].crouchkeydown=1;
5799                     }
5800             //walked off a ledge (?)
5801             if(player[i].isRun()&&!player[i].onground)
5802                 if(player[i].coords.y>terrain.getHeight(player[i].coords.x,player[i].coords.z)+10){
5803                     XYZ test2=player[i].coords+player[i].facing;
5804                     test2.y+=5;
5805                     XYZ test=player[i].coords+player[i].facing;
5806                     test.y-=10;
5807                     j=checkcollide(test2,test,player[i].laststanding);
5808                     if(j==-1)
5809                         j=checkcollide(test2,test);
5810                     if(j==-1){
5811                         player[i].velocity=0;
5812                         setAnimation(i,player[i].getStop());
5813                         player[i].targetrotation+=180;
5814                         player[i].stunned=.5;
5815                         player[i].aitype=pathfindtype;
5816                         player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
5817                         player[i].finalpathfindpoint=-1;
5818                         player[i].targetpathfindpoint=-1;
5819                         player[i].lastpathfindpoint=-1;
5820                         player[i].lastpathfindpoint2=-1;
5821                         player[i].lastpathfindpoint3=-1;
5822                         player[i].lastpathfindpoint4=-1;
5823                     }else
5824                         player[i].laststanding=j;
5825                 }
5826             //lose sight of player in the air (?)
5827             if(player[0].coords.y>player[i].coords.y+5&&
5828                     animation[player[0].targetanimation].height!=highheight&&
5829                     !player[0].onterrain){
5830                 player[i].aitype=pathfindtype;
5831                 player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
5832                 player[i].finalpathfindpoint=-1;
5833                 player[i].targetpathfindpoint=-1;
5834                 player[i].lastpathfindpoint=-1;
5835                 player[i].lastpathfindpoint2=-1;
5836                 player[i].lastpathfindpoint3=-1;
5837                 player[i].lastpathfindpoint4=-1;
5838             }
5839             //it's time to think (?)
5840             if(player[i].aiupdatedelay<0&&
5841                     !animation[player[i].targetanimation].attack&&
5842                     player[i].targetanimation!=staggerbackhighanim&&
5843                     player[i].targetanimation!=staggerbackhardanim&&
5844                     player[i].targetanimation!=backhandspringanim&&
5845                     player[i].targetanimation!=dodgebackanim){
5846                 //draw weapon
5847                 if(player[i].weaponactive==-1&&player[i].num_weapons>0)
5848                     player[i].drawkeydown=Random()%2;
5849                 else
5850                     player[i].drawkeydown=0;
5851                 player[i].rabbitkickenabled=Random()%2;
5852                 //chase player
5853                 XYZ rotatetarget=player[0].coords+player[0].velocity;
5854                 XYZ targetpoint=player[0].coords;
5855                 if(findDistancefast(&player[0].coords,&player[i].coords)<
5856                         findDistancefast(&rotatetarget,&player[i].coords))
5857                     targetpoint+=player[0].velocity*
5858                         findDistance(&player[0].coords,&player[i].coords)/findLength(&player[i].velocity);
5859                 player[i].targetrotation=roughDirectionTo(player[i].coords,targetpoint);
5860                 player[i].lookrotation=player[i].targetrotation;
5861                 player[i].aiupdatedelay=.2+fabs((float)(Random()%100)/1000);
5862
5863                 if(findDistancefast(&player[i].coords,&player[0].coords)>5&&(player[0].weaponactive==-1||player[i].weaponactive!=-1))
5864                     player[i].forwardkeydown=1;
5865                 else if((findDistancefast(&player[i].coords,&player[0].coords)>16||
5866                             findDistancefast(&player[i].coords,&player[0].coords)<9)&&
5867                         player[0].weaponactive!=-1)
5868                     player[i].forwardkeydown=1;
5869                 else if(Random()%6==0||(player[i].creature==wolftype&&Random()%3==0))
5870                     player[i].forwardkeydown=1;
5871                 else
5872                     player[i].forwardkeydown=0;
5873                 //chill out around the corpse
5874                 if(player[0].dead){
5875                     player[i].forwardkeydown=0;
5876                     if(Random()%10==0)
5877                         player[i].forwardkeydown=1;
5878                     if(Random()%100==0){
5879                         player[i].aitype=pathfindtype;
5880                         player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
5881                         player[i].finalpathfindpoint=-1;
5882                         player[i].targetpathfindpoint=-1;
5883                         player[i].lastpathfindpoint=-1;
5884                         player[i].lastpathfindpoint2=-1;
5885                         player[i].lastpathfindpoint3=-1;
5886                         player[i].lastpathfindpoint4=-1;
5887                     }
5888                 }
5889                 player[i].leftkeydown=0;
5890                 player[i].backkeydown=0;
5891                 player[i].rightkeydown=0;
5892                 player[i].crouchkeydown=0;
5893                 player[i].throwkeydown=0;
5894
5895                 if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8)
5896                     player[i].targetrotation+=90*(player[i].whichdirection*2-1);
5897                 //attack!!!
5898                 if(Random()%2==0||player[i].weaponactive!=-1||player[i].creature==wolftype)
5899                     player[i].attackkeydown=1;
5900                 else
5901                     player[i].attackkeydown=0;
5902                 if(player[i].isRun()&&Random()%6&&findDistancefast(&player[i].coords,&player[0].coords)>7)
5903                     player[i].attackkeydown=0;
5904
5905                 //TODO: wat
5906                 if(player[i].aitype!=playercontrolled&&
5907                         (player[i].isIdle()||
5908                          player[i].isCrouch()||
5909                          player[i].isRun())){
5910                     int target=-2;
5911                     for(int j=0;j<numplayers;j++)
5912                         if(j!=i&&!player[j].skeleton.free&&
5913                                 player[j].hasvictim&&
5914                                 (tutoriallevel==1&&reversaltrain||
5915                                  Random()%2==0&&difficulty==2||
5916                                  Random()%4==0&&difficulty==1||
5917                                  Random()%8==0&&difficulty==0||
5918                                  player[j].lastattack2==player[j].targetanimation&&
5919                                  player[j].lastattack3==player[j].targetanimation&&
5920                                  (Random()%2==0||difficulty==2)||
5921                                  (player[i].isIdle()||player[i].isRun())&&
5922                                  player[j].weaponactive!=-1||
5923                                  player[j].targetanimation==swordslashanim&&
5924                                  player[i].weaponactive!=-1||
5925                                  player[j].targetanimation==staffhitanim||
5926                                  player[j].targetanimation==staffspinhitanim))
5927                             if(findDistancefast(&player[j].coords,&player[j].victim->coords)<4&&
5928                                     player[j].victim==&player[i]&&
5929                                     (player[j].targetanimation==sweepanim||
5930                                      player[j].targetanimation==spinkickanim||
5931                                      player[j].targetanimation==staffhitanim||
5932                                      player[j].targetanimation==staffspinhitanim||
5933                                      player[j].targetanimation==winduppunchanim||
5934                                      player[j].targetanimation==upunchanim||
5935                                      player[j].targetanimation==wolfslapanim||
5936                                      player[j].targetanimation==knifeslashstartanim||
5937                                      player[j].targetanimation==swordslashanim&&
5938                                       (findDistancefast(&player[j].coords,&player[i].coords)<2||
5939                                        player[i].weaponactive!=-1))){
5940                                 if(target>=0)
5941                                     target=-1;
5942                                 else
5943                                     target=j;
5944                             }
5945                     if(target>=0)
5946                         player[target].Reverse();
5947                 }
5948
5949                 if(player[i].collided<1)
5950                     player[i].jumpkeydown=0;
5951                 if(player[i].collided>.8&&player[i].jumppower>=5||
5952                         findDistancefast(&player[i].coords,&player[0].coords)>400&&
5953                         player[i].onterrain&&
5954                         player[i].creature==rabbittype)
5955                     player[i].jumpkeydown=1;
5956                 //TODO: why are we controlling the human?
5957                 if(normaldotproduct(player[i].facing,player[0].coords-player[i].coords)>0)
5958                     player[0].jumpkeydown=0;
5959                 if(player[0].targetanimation==jumpdownanim&&
5960                         findDistancefast(&player[0].coords,&player[i].coords)<40)
5961                     player[i].crouchkeydown=1;
5962                 if(player[i].jumpkeydown)
5963                     player[i].attackkeydown=0;
5964
5965                 if(tutoriallevel==1)
5966                     if(!canattack)
5967                         player[i].attackkeydown=0;
5968
5969
5970                 XYZ facing=player[i].coords;
5971                 XYZ flatfacing=player[0].coords;
5972                 facing.y+=playerJoint(i,head).position.y*player[i].scale;
5973                 flatfacing.y+=playerJoint(0,head).position.y*player[0].scale;
5974                 if(player[i].occluded>=2)
5975                     if(-1!=checkcollide(facing,flatfacing)){
5976                         if(!player[i].pause)
5977                             player[i].lastseentime-=.2;
5978                         if(player[i].lastseentime<=0&&
5979                                 (player[i].creature!=wolftype||
5980                                  player[i].weaponstuck==-1)){
5981                             player[i].aitype=searchtype;
5982                             player[i].lastchecktime=12;
5983                             player[i].lastseen=player[0].coords;
5984                             player[i].lastseentime=12;
5985                         }
5986                     }else
5987                         player[i].lastseentime=1;
5988             }
5989         }
5990         if(animation[player[0].targetanimation].height==highheight&&
5991                 (player[i].aitype==attacktypecutoff||
5992                  player[i].aitype==searchtype))
5993             if(player[0].coords.y>terrain.getHeight(player[0].coords.x,player[0].coords.z)+10){
5994                 XYZ test=player[0].coords;
5995                 test.y-=40;
5996                 if(-1==checkcollide(player[0].coords,test))
5997                     player[i].stunned=1;
5998             }
5999         //stunned
6000         if(player[i].aitype==passivetype&&!(player[i].numwaypoints>1)||
6001                 player[i].stunned>0||
6002                 player[i].pause&&player[i].damage>player[i].superpermanentdamage){
6003             if(player[i].pause)
6004                 player[i].lastseentime=1;
6005             player[i].targetrotation=player[i].rotation;
6006             player[i].forwardkeydown=0;
6007             player[i].leftkeydown=0;
6008             player[i].backkeydown=0;
6009             player[i].rightkeydown=0;
6010             player[i].jumpkeydown=0;
6011             player[i].attackkeydown=0;
6012             player[i].crouchkeydown=0;
6013             player[i].throwkeydown=0;
6014         }
6015
6016
6017         XYZ facing;
6018         facing=0;
6019         facing.z=-1;
6020
6021         XYZ flatfacing=DoRotation(facing,0,player[i].rotation+180,0);
6022         facing=flatfacing;
6023
6024         if(player[i].aitype==attacktypecutoff){
6025             player[i].targetheadrotation=180-roughDirectionTo(player[i].coords,player[0].coords);
6026             player[i].targetheadrotation2=pitchTo(player[i].coords,player[0].coords);
6027         }else if(player[i].howactive>=typesleeping){
6028             player[i].targetheadrotation=player[i].targetrotation;
6029             player[i].targetheadrotation2=0;
6030         }else{
6031             if(player[i].interestdelay<=0){
6032                 player[i].interestdelay=.7+(float)(abs(Random()%100))/100;
6033                 player[i].headtarget=player[i].coords;
6034                 player[i].headtarget.x+=(float)(abs(Random()%200)-100)/100;
6035                 player[i].headtarget.z+=(float)(abs(Random()%200)-100)/100;
6036                 player[i].headtarget.y+=(float)(abs(Random()%200)-100)/300;
6037                 player[i].headtarget+=player[i].facing*1.5;
6038             }
6039             player[i].targetheadrotation=180-roughDirectionTo(player[i].coords,player[i].headtarget);
6040             player[i].targetheadrotation2=pitchTo(player[i].coords,player[i].headtarget);
6041         }
6042     }
6043 }
6044
6045
6046
6047 void Game::Tick(){
6048         static XYZ facing,flatfacing;
6049         static int target;
6050
6051         int templength;
6052
6053         for(int i=0;i<15;i++){
6054                 displaytime[i]+=multiplier;
6055         }
6056
6057         keyboardfrozen=0;
6058     Input::Tick();
6059
6060         if(Input::isKeyPressed(SDLK_F6)){
6061                 if(Input::isKeyDown(SDLK_LSHIFT))
6062                         stereoreverse=true;
6063                 else
6064                         stereoreverse=false;
6065
6066                 if(stereoreverse)
6067                         printf("Stereo reversed\n");
6068                 else
6069                         printf("Stereo unreversed\n");
6070         }
6071
6072         if(Input::isKeyDown(SDLK_F7)){
6073                 if(Input::isKeyDown(SDLK_LSHIFT))
6074                         stereoseparation -= 0.001;
6075                 else
6076                         stereoseparation -= 0.010;
6077                 printf("Stereo decreased increased to %f\n", stereoseparation);
6078         }
6079
6080         if(Input::isKeyDown(SDLK_F8)){
6081                 if(Input::isKeyDown(SDLK_LSHIFT))
6082                         stereoseparation += 0.001;
6083                 else
6084                         stereoseparation += 0.010;
6085                 printf("Stereo separation increased to %f\n", stereoseparation);
6086         }
6087
6088
6089         if(Input::isKeyPressed(SDLK_TAB)&&tutoriallevel){
6090                 if(tutorialstage!=51)
6091                         tutorialstagetime=tutorialmaxtime;
6092                 emit_sound_np(consolefailsound, 128.);
6093         }
6094
6095         if(!console){
6096                 if(mainmenu&&endgame==1)mainmenu=10;
6097         // menu back
6098                 if( (Input::isKeyPressed(SDLK_ESCAPE)
6099                     ||(mainmenu==0
6100                         &&((Input::isKeyPressed(jumpkey)
6101                                 ||Input::isKeyPressed(SDLK_SPACE)
6102                                 ||(campaign)))
6103                         &&campaign
6104                         &&winfreeze))
6105                 && (!mainmenu||gameon||mainmenu==3||mainmenu==4||mainmenu==5||mainmenu==6||(mainmenu==7&&!entername)||mainmenu==9||mainmenu==10)){
6106                         selected=-1;
6107                         if(mainmenu==1||mainmenu==2||mainmenu==0){
6108                                 if(mainmenu==0&&!winfreeze)mainmenu=2;
6109                                 else if(mainmenu==0&&winfreeze&&(campaignchoosenext[campaignchoicewhich[whichchoice]])==1)mainmenu=100;
6110                                 else if(mainmenu==0&&winfreeze){ }
6111                                 else if(mainmenu==1||mainmenu==2)mainmenu=0;
6112                                 if(mainmenu&&musictoggle){
6113                                         if(mainmenu==1||mainmenu==2||mainmenu==100){
6114                                                 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6115                                                 emit_stream_np(stream_music3);
6116                                                 pause_sound(music1);
6117                                         }
6118                                 }
6119                                 if(!mainmenu){
6120                                         pause_sound(stream_music3);
6121                                         resume_stream(music1);
6122                                 }
6123                         }
6124                         if(mainmenu==3){
6125                                 if(newdetail>2)newdetail=detail;
6126                                 if(newdetail<0)newdetail=detail;
6127                                 if(newscreenwidth<0)newscreenwidth=screenwidth;
6128                                 if(newscreenheight<0)newscreenheight=screenheight;
6129                                 SaveSettings(*this);
6130                         }
6131                         if((mainmenu>=3 && mainmenu<=7)||mainmenu==9||mainmenu==10||mainmenu==100){
6132                                 fireSound();
6133                                 flash();
6134                         }
6135                         if(mainmenu==3&&gameon)mainmenu=2;
6136                         if(mainmenu==3&&!gameon)mainmenu=1;
6137                         if(mainmenu==5&&gameon)mainmenu=2;
6138                         if(mainmenu==5&&!gameon)mainmenu=1;
6139                         if(mainmenu==4)mainmenu=3;
6140                         if(mainmenu==6)mainmenu=5;
6141                         if(mainmenu==7)mainmenu=1;
6142                         if(mainmenu==9)mainmenu=5;
6143                         if(mainmenu==10)mainmenu=5;
6144                         if(mainmenu==100){
6145                                 mainmenu=5;
6146                                 gameon=0;
6147                                 winfreeze=0;
6148                         }
6149                 }
6150         }
6151
6152         if(mainmenu){
6153         MenuTick();
6154         }
6155
6156         if(!mainmenu){
6157                 if(hostile==1)hostiletime+=multiplier;
6158                 else hostiletime=0;
6159                 if(!winfreeze)leveltime+=multiplier;
6160
6161         //keys
6162                 if(Input::isKeyDown(SDLK_ESCAPE)){
6163                         chatting=0;
6164                         console=0;
6165                         freeze=0;
6166                         displaychars[0]=0;
6167                 }
6168
6169                 if(Input::isKeyPressed(chatkey)&&!console&&!chatting&&debugmode)
6170                         chatting=1;
6171
6172                 if(chatting){
6173                         inputText(displaytext[0],&displayselected,&displaychars[0]);
6174                         if(!waiting) {
6175                                 if(displaychars[0]){
6176                                         for(int j=0;j<255;j++){
6177                                                 displaytext[0][j]=' ';
6178                                         }
6179                                         displaychars[0]=0;
6180                                         displayselected=0;
6181                                 }       
6182                                 chatting=0;             
6183                         }
6184
6185                         displayblinkdelay-=multiplier;
6186                         if(displayblinkdelay<=0){
6187                                 displayblinkdelay=.3;
6188                                 displayblink=1-displayblink;
6189                         }
6190                 }
6191                 if(chatting)
6192             keyboardfrozen=1;
6193
6194                 if(Input::isKeyDown(SDLK_q)&&Input::isKeyDown(SDLK_LMETA)){
6195                         tryquit=1;
6196                         if(mainmenu==3){
6197                                 if(newdetail>2)newdetail=detail;
6198                                 if(newdetail<0)newdetail=detail;
6199                                 if(newscreenwidth<0)newscreenwidth=screenwidth;
6200                                 if(newscreenheight<0)newscreenheight=screenheight;
6201
6202                                 SaveSettings(*this);
6203                         }
6204                 }
6205
6206                 static int oldwinfreeze;
6207                 if(winfreeze&&!oldwinfreeze){
6208                         OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6209                         emit_sound_np(consolesuccesssound);
6210                 }
6211                 if(winfreeze==0)
6212             oldwinfreeze=winfreeze;
6213                 else
6214             oldwinfreeze++;
6215
6216                 if((Input::isKeyPressed(jumpkey)||Input::isKeyPressed(SDLK_SPACE))&&!campaign)
6217                         if(winfreeze)
6218                 winfreeze=0;
6219                 if((Input::isKeyDown(SDLK_ESCAPE))&&!campaign&&gameon)
6220                         if(winfreeze){
6221                                 mainmenu=9;
6222                                 gameon=0;
6223                         }
6224
6225
6226         //TODO: what is this test?
6227                 if(!freeze&&!winfreeze&&!(mainmenu&&gameon)&&(gameon||!gamestarted)){
6228
6229             //dialogues
6230                         if(indialogue!=-1)
6231                 talkdelay=1;
6232                         talkdelay-=multiplier;
6233
6234                         if(talkdelay<=0&&indialogue==-1&&animation[player[0].targetanimation].height!=highheight)
6235                 for(int i=0;i<numdialogues;i++){
6236                     int realdialoguetype;
6237                     bool special;
6238                     if(dialoguetype[i]>49){
6239                         realdialoguetype=dialoguetype[i]-50;
6240                         special=1;
6241                     }
6242                     else if(dialoguetype[i]>39){
6243                         realdialoguetype=dialoguetype[i]-40;
6244                         special=1;
6245                     }
6246                     else if(dialoguetype[i]>29){
6247                         realdialoguetype=dialoguetype[i]-30;
6248                         special=1;
6249                     }
6250                     else if(dialoguetype[i]>19){
6251                         realdialoguetype=dialoguetype[i]-20;
6252                         special=1;
6253                     }
6254                     else if(dialoguetype[i]>9){
6255                         realdialoguetype=dialoguetype[i]-10;
6256                         special=1;
6257                     }
6258                     else {
6259                         realdialoguetype=dialoguetype[i];
6260                         special=0;
6261                     }
6262                     if((!hostile||dialoguetype[i]>40&&dialoguetype[i]<50)&&
6263                             realdialoguetype<numplayers&&
6264                             realdialoguetype>0&&
6265                             (dialoguegonethrough[i]==0||!special)&&
6266                             (special||Input::isKeyPressed(attackkey))){
6267                         if(findDistancefast(&player[0].coords,&player[realdialoguetype].coords)<6||
6268                                 player[realdialoguetype].howactive>=typedead1||
6269                                 dialoguetype[i]>40&&dialoguetype[i]<50){
6270                             whichdialogue=i;
6271                             for(int j=0;j<numdialogueboxes[whichdialogue];j++){
6272                                 player[participantfocus[whichdialogue][j]].coords=participantlocation[whichdialogue][participantfocus[whichdialogue][j]];
6273                                 player[participantfocus[whichdialogue][j]].rotation=participantrotation[whichdialogue][participantfocus[whichdialogue][j]];
6274                                 player[participantfocus[whichdialogue][j]].targetrotation=participantrotation[whichdialogue][participantfocus[whichdialogue][j]];
6275                                 player[participantfocus[whichdialogue][j]].velocity=0;
6276                                 player[participantfocus[whichdialogue][j]].targetanimation=player[participantfocus[whichdialogue][j]].getIdle();
6277                                 player[participantfocus[whichdialogue][j]].targetframe=0;
6278                             }
6279                             directing=0;
6280                             indialogue=0;
6281                             dialoguetime=0;
6282                             dialoguegonethrough[i]++;
6283                             if(dialogueboxsound[whichdialogue][indialogue]!=0){
6284                                 playdialogueboxsound();
6285                             }
6286                         }
6287                     }
6288                 }
6289
6290             windvar+=multiplier;
6291             smoketex+=multiplier;
6292             tutorialstagetime+=multiplier;
6293
6294             //hotspots
6295             static float hotspotvisual[40];
6296             if(numhotspots){
6297                 XYZ hotspotsprite;
6298                 if(editorenabled)
6299                     for(int i=0;i<numhotspots;i++)
6300                         hotspotvisual[i]-=multiplier/320;
6301
6302                 for(int i=0;i<numhotspots;i++){
6303                     //if(hotspottype[i]<=10)
6304                     while(hotspotvisual[i]<0){
6305                         hotspotsprite=0;
6306                         hotspotsprite.x=float(abs(Random()%100000))/100000*hotspotsize[i];
6307                         hotspotsprite=DoRotation(hotspotsprite,0,0,Random()%360);
6308                         hotspotsprite=DoRotation(hotspotsprite,0,Random()%360,0);
6309                         hotspotsprite+=hotspot[i];
6310                         Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite*0, 1,0.5,0, 7, 0.4);
6311                         hotspotvisual[i]+=0.1/hotspotsize[i]/hotspotsize[i]/hotspotsize[i];
6312                     }
6313                 }
6314
6315                 for(int i=0;i<numhotspots;i++){
6316                     if(hotspottype[i]<=10&&hotspottype[i]>0){
6317                         hotspot[i]=player[hotspottype[i]].coords;
6318                     }
6319                 }
6320             }
6321
6322             //Tutorial
6323             if(tutoriallevel){
6324                 doTutorial();
6325             }
6326
6327             //bonuses
6328             if(tutoriallevel!=1){
6329                 if(bonustime==0&&
6330                         bonus!=solidhit&&
6331                         bonus!=spinecrusher&&
6332                         bonus!=tracheotomy&&
6333                         bonus!=backstab&&
6334                         bonusvalue>10){
6335                     emit_sound_np(consolesuccesssound);
6336                 }
6337             } else if(bonustime==0){
6338                 emit_sound_np(fireendsound);
6339             }
6340             if(bonustime==0){
6341                 if(bonus!=solidhit&&
6342                         bonus!=twoxcombo&&
6343                         bonus!=threexcombo&&
6344                         bonus!=fourxcombo&&
6345                         bonus!=megacombo)
6346                     bonusnum[bonus]++;
6347                 else
6348                     bonusnum[bonus]+=0.15;
6349                 if(tutoriallevel)
6350                     bonusvalue=0;
6351                 bonusvalue/=bonusnum[bonus];
6352                 bonustotal+=bonusvalue;
6353             }
6354             bonustime+=multiplier;
6355
6356             //snow effects
6357             if(environment==snowyenvironment){
6358                 precipdelay-=multiplier;
6359                 while(precipdelay<0){
6360                     precipdelay+=.04;
6361                     if(!detail)
6362                         precipdelay+=.04;
6363                     XYZ footvel,footpoint;
6364
6365                     footvel=0;
6366                     footpoint=viewer+viewerfacing*6;
6367                     footpoint.y+=((float)abs(Random()%1200))/100-6;
6368                     footpoint.x+=((float)abs(Random()%1200))/100-6;
6369                     footpoint.z+=((float)abs(Random()%1200))/100-6;
6370                     Sprite::MakeSprite(snowsprite, footpoint,footvel, 1,1,1, .1, 1);
6371                 }
6372             }
6373
6374
6375             doAerialAcrobatics();
6376
6377
6378             static XYZ oldviewer;
6379
6380             //control keys
6381             if(indialogue==-1){
6382                 player[0].forwardkeydown=Input::isKeyDown(forwardkey);
6383                 player[0].leftkeydown=Input::isKeyDown(leftkey);
6384                 player[0].backkeydown=Input::isKeyDown(backkey);
6385                 player[0].rightkeydown=Input::isKeyDown(rightkey);
6386                 player[0].jumpkeydown=Input::isKeyDown(jumpkey);
6387                 player[0].crouchkeydown=Input::isKeyDown(crouchkey);
6388                 player[0].drawkeydown=Input::isKeyDown(drawkey);
6389                 player[0].throwkeydown=Input::isKeyDown(throwkey);
6390             }
6391             else
6392             {
6393                 player[0].forwardkeydown=0;
6394                 player[0].leftkeydown=0;
6395                 player[0].backkeydown=0;
6396                 player[0].rightkeydown=0;
6397                 player[0].jumpkeydown=0;
6398                 player[0].crouchkeydown=0;
6399                 player[0].drawkeydown=0;
6400                 player[0].throwkeydown=0;
6401             }
6402
6403             if(!player[0].jumpkeydown)
6404                 player[0].jumpclimb=0;
6405
6406
6407             if(indialogue!=-1){
6408                 cameramode=1;
6409                 if(directing){
6410                     facing=0;
6411                     facing.z=-1;
6412
6413                     facing=DoRotation(facing,-rotation2,0,0);
6414                     facing=DoRotation(facing,0,0-rotation,0);
6415
6416                     flatfacing=0;
6417                     flatfacing.z=-1;
6418
6419                     flatfacing=DoRotation(flatfacing,0,-rotation,0);
6420
6421                     if(Input::isKeyDown(forwardkey))
6422                         viewer+=facing*multiplier*4;
6423                     if(Input::isKeyDown(backkey))
6424                         viewer-=facing*multiplier*4;
6425                     if(Input::isKeyDown(leftkey))
6426                         viewer+=DoRotation(flatfacing*multiplier,0,90,0)*4;
6427                     if(Input::isKeyDown(rightkey))
6428                         viewer+=DoRotation(flatfacing*multiplier,0,-90,0)*4;
6429                     if(Input::isKeyDown(jumpkey))
6430                         viewer.y+=multiplier*4;
6431                     if(Input::isKeyDown(crouchkey))
6432                         viewer.y-=multiplier*4;
6433                     if(     Input::isKeyPressed(SDLK_1)||
6434                             Input::isKeyPressed(SDLK_2)||
6435                             Input::isKeyPressed(SDLK_3)||
6436                             Input::isKeyPressed(SDLK_4)||
6437                             Input::isKeyPressed(SDLK_5)||
6438                             Input::isKeyPressed(SDLK_6)||
6439                             Input::isKeyPressed(SDLK_7)||
6440                             Input::isKeyPressed(SDLK_8)||
6441                             Input::isKeyPressed(SDLK_9)||
6442                             Input::isKeyPressed(SDLK_0)||
6443                             Input::isKeyPressed(SDLK_MINUS)){
6444                         int whichend;
6445                         if(Input::isKeyPressed(SDLK_1))whichend=1;
6446                         if(Input::isKeyPressed(SDLK_2))whichend=2;
6447                         if(Input::isKeyPressed(SDLK_3))whichend=3;
6448                         if(Input::isKeyPressed(SDLK_4))whichend=4;
6449                         if(Input::isKeyPressed(SDLK_5))whichend=5;
6450                         if(Input::isKeyPressed(SDLK_6))whichend=6;
6451                         if(Input::isKeyPressed(SDLK_7))whichend=7;
6452                         if(Input::isKeyPressed(SDLK_8))whichend=8;
6453                         if(Input::isKeyPressed(SDLK_9))whichend=9;
6454                         if(Input::isKeyPressed(SDLK_0))whichend=0;
6455                         if(Input::isKeyPressed(SDLK_MINUS))
6456                             whichend=-1;
6457                         if(whichend!=-1){
6458                             participantfocus[whichdialogue][indialogue]=whichend;
6459                             participantlocation[whichdialogue][whichend]=player[whichend].coords;
6460                             participantrotation[whichdialogue][whichend]=player[whichend].rotation;
6461                         }
6462                         if(whichend==-1){
6463                             participantfocus[whichdialogue][indialogue]=-1;
6464                         }
6465                         if(player[participantfocus[whichdialogue][indialogue]].dead){
6466                             indialogue=-1;
6467                             directing=0;
6468                             cameramode=0;
6469                         }
6470                         dialoguecamera[whichdialogue][indialogue]=viewer;
6471                         dialoguecamerarotation[whichdialogue][indialogue]=rotation;
6472                         dialoguecamerarotation2[whichdialogue][indialogue]=rotation2;
6473                         indialogue++;
6474                         if(indialogue<numdialogueboxes[whichdialogue]){
6475                             if(dialogueboxsound[whichdialogue][indialogue]!=0){
6476                                 playdialogueboxsound();
6477                             }
6478                         }
6479
6480                         for(int j=0;j<numplayers;j++){
6481                             participantfacing[whichdialogue][indialogue][j]=participantfacing[whichdialogue][indialogue-1][j];
6482                         }
6483                     }
6484                     //TODO: should these be KeyDown or KeyPressed?
6485                     if(     Input::isKeyDown(SDLK_KP1)||
6486                             Input::isKeyDown(SDLK_KP2)||
6487                             Input::isKeyDown(SDLK_KP3)||
6488                             Input::isKeyDown(SDLK_KP4)||
6489                             Input::isKeyDown(SDLK_KP5)||
6490                             Input::isKeyDown(SDLK_KP6)||
6491                             Input::isKeyDown(SDLK_KP7)||
6492                             Input::isKeyDown(SDLK_KP8)||
6493                             Input::isKeyDown(SDLK_KP9)||
6494                             Input::isKeyDown(SDLK_KP0)){
6495                         int whichend;
6496                         if(Input::isKeyDown(SDLK_KP1))whichend=1;
6497                         if(Input::isKeyDown(SDLK_KP2))whichend=2;
6498                         if(Input::isKeyDown(SDLK_KP3))whichend=3;
6499                         if(Input::isKeyDown(SDLK_KP4))whichend=4;
6500                         if(Input::isKeyDown(SDLK_KP5))whichend=5;
6501                         if(Input::isKeyDown(SDLK_KP6))whichend=6;
6502                         if(Input::isKeyDown(SDLK_KP7))whichend=7;
6503                         if(Input::isKeyDown(SDLK_KP8))whichend=8;
6504                         if(Input::isKeyDown(SDLK_KP9))whichend=9;
6505                         if(Input::isKeyDown(SDLK_KP0))whichend=0;
6506                         participantfacing[whichdialogue][indialogue][whichend]=facing;
6507                     }
6508                     if(indialogue>=numdialogueboxes[whichdialogue]){
6509                         indialogue=-1;
6510                         directing=0;
6511                         cameramode=0;
6512                     }
6513                 }
6514                 if(!directing){
6515                     pause_sound(whooshsound);
6516                     viewer=dialoguecamera[whichdialogue][indialogue];
6517                     viewer.y=max((double)viewer.y,terrain.getHeight(viewer.x,viewer.z)+.1);
6518                     rotation=dialoguecamerarotation[whichdialogue][indialogue];
6519                     rotation2=dialoguecamerarotation2[whichdialogue][indialogue];
6520                     if(dialoguetime>0.5)
6521                         if(     Input::isKeyPressed(SDLK_1)||
6522                                 Input::isKeyPressed(SDLK_2)||
6523                                 Input::isKeyPressed(SDLK_3)||
6524                                 Input::isKeyPressed(SDLK_4)||
6525                                 Input::isKeyPressed(SDLK_5)||
6526                                 Input::isKeyPressed(SDLK_6)||
6527                                 Input::isKeyPressed(SDLK_7)||
6528                                 Input::isKeyPressed(SDLK_8)||
6529                                 Input::isKeyPressed(SDLK_9)||
6530                                 Input::isKeyPressed(SDLK_0)||
6531                                 Input::isKeyPressed(SDLK_MINUS)||
6532                                 Input::isKeyPressed(attackkey)){
6533                             indialogue++;
6534                             if(indialogue<numdialogueboxes[whichdialogue]){
6535                                 if(dialogueboxsound[whichdialogue][indialogue]!=0){
6536                                     playdialogueboxsound();
6537                                     if(dialogueboxsound[whichdialogue][indialogue]==-5){
6538                                         hotspot[numhotspots]=player[0].coords;
6539                                         hotspotsize[numhotspots]=10;
6540                                         hotspottype[numhotspots]=-1;
6541
6542                                         numhotspots++;
6543                                     }
6544                                     if(dialogueboxsound[whichdialogue][indialogue]==-6){
6545                                         hostile=1;
6546                                     }
6547
6548                                     if(player[participantfocus[whichdialogue][indialogue]].dead){
6549                                         indialogue=-1;
6550                                         directing=0;
6551                                         cameramode=0;
6552                                     }
6553                                 }
6554                             }
6555                         }
6556                     if(indialogue>=numdialogueboxes[whichdialogue]){
6557                         indialogue=-1;
6558                         directing=0;
6559                         cameramode=0;
6560                         if(dialoguetype[whichdialogue]>19&&dialoguetype[whichdialogue]<30){
6561                             hostile=1;
6562                         }
6563                         if(dialoguetype[whichdialogue]>29&&dialoguetype[whichdialogue]<40){
6564                             windialogue=1;
6565                         }
6566                         if(dialoguetype[whichdialogue]>49&&dialoguetype[whichdialogue]<60){
6567                             hostile=1;
6568                             for(int i=1;i<numplayers;i++){
6569                                 player[i].aitype = attacktypecutoff;
6570                             }
6571                         }
6572                     }
6573                 }
6574             }
6575
6576             static float keyrefreshdelay=0,bigrefreshdelay=0;
6577
6578             if(!player[0].jumpkeydown){
6579                 player[0].jumptogglekeydown=0;
6580             }
6581             if(player[0].jumpkeydown&&
6582                     player[0].targetanimation!=jumpupanim&&
6583                     player[0].targetanimation!=jumpdownanim&&
6584                     !player[0].isFlip())
6585                 player[0].jumptogglekeydown=1;
6586
6587
6588             dialoguetime+=multiplier;
6589             hawkrotation+=multiplier*25;
6590             realhawkcoords=0;
6591             realhawkcoords.x=25;
6592             realhawkcoords=DoRotation(realhawkcoords,0,hawkrotation,0)+hawkcoords;
6593             hawkcalldelay-=multiplier/2;
6594
6595             if(hawkcalldelay<=0){
6596                 emit_sound_at(hawksound, realhawkcoords);
6597
6598                 hawkcalldelay=16+abs(Random()%8);
6599             }
6600             static float temptexdetail;
6601
6602
6603             doDebugKeys();
6604
6605             doAttacks();
6606
6607             doPlayerCollisions();
6608
6609             doJumpReversals();
6610
6611             for(int k=0;k<numplayers;k++)
6612                 if(k!=0&&player[k].immobile)
6613                     player[k].coords=player[k].realoldcoords;
6614
6615             for(int k=0;k<numplayers;k++){
6616                 if(!isnormal(player[k].coords.x)||!isnormal(player[k].coords.y)||!isnormal(player[k].coords.z)){
6617                     if(!isnormal(player[k].coords.x)||!isnormal(player[k].coords.y)||!isnormal(player[k].coords.z)){
6618                         player[k].DoDamage(1000);
6619                     }
6620                 }
6621             }
6622
6623             //respawn
6624             static bool respawnkeydown;
6625             if(!editorenabled&&
6626                     (whichlevel!=-2&&
6627                      (Input::isKeyDown(SDLK_z)&&
6628                       Input::isKeyDown(SDLK_LMETA)&&
6629                       debugmode)||
6630                      (Input::isKeyDown(jumpkey)&&
6631                       !respawnkeydown&&
6632                       !oldattackkey&&
6633                       player[0].dead))){
6634                 targetlevel=whichlevel;
6635                 loading=1;
6636                 leveltime=5;
6637             }
6638             if(!Input::isKeyDown(jumpkey))
6639                 respawnkeydown=0;
6640             if(Input::isKeyDown(jumpkey))
6641                 respawnkeydown=1;
6642
6643
6644
6645
6646             static bool movekey;
6647
6648             //?
6649             for(int i=0;i<numplayers;i++){
6650                 static float oldtargetrotation;
6651                 if(!player[i].skeleton.free){
6652                     oldtargetrotation=player[i].targetrotation;
6653                     if(i==0&&indialogue==-1){
6654                         //TODO: refactor repetitive code
6655                         if(!animation[player[0].targetanimation].attack&&
6656                                 player[0].targetanimation!=staggerbackhighanim&&
6657                                 player[0].targetanimation!=staggerbackhardanim&&
6658                                 player[0].targetanimation!=crouchremoveknifeanim&&
6659                                 player[0].targetanimation!=removeknifeanim&&
6660                                 player[0].targetanimation!=backhandspringanim&&
6661                                 player[0].targetanimation!=dodgebackanim&&
6662                                 player[0].targetanimation!=walljumprightkickanim&&
6663                                 player[0].targetanimation!=walljumpleftkickanim){
6664                             if(cameramode)
6665                                 player[0].targetrotation=0;
6666                             else
6667                                 player[0].targetrotation=-rotation+180;
6668                         }
6669
6670                         facing=0;
6671                         facing.z=-1;
6672
6673                         flatfacing=DoRotation(facing,0,player[i].rotation+180,0);
6674                         if(cameramode){
6675                             facing=flatfacing;
6676                         }else{
6677                             facing=DoRotation(facing,-rotation2,0,0);
6678                             facing=DoRotation(facing,0,0-rotation,0);
6679                         }
6680
6681                         player[0].lookrotation=-rotation;
6682
6683                         player[i].targetheadrotation=rotation;
6684                         player[i].targetheadrotation2=rotation2;
6685                     }
6686                     if(i!=0&&player[i].aitype==playercontrolled&&indialogue==-1){
6687                         if(!animation[player[i].targetanimation].attack&&
6688                                 player[i].targetanimation!=staggerbackhighanim&&
6689                                 player[i].targetanimation!=staggerbackhardanim&&
6690                                 player[i].targetanimation!=crouchremoveknifeanim&&
6691                                 player[i].targetanimation!=removeknifeanim&&
6692                                 player[i].targetanimation!=backhandspringanim&&
6693                                 player[i].targetanimation!=dodgebackanim&&
6694                                 player[i].targetanimation!=walljumprightkickanim&&
6695                                 player[i].targetanimation!=walljumpleftkickanim){
6696                             player[i].targetrotation=-player[i].lookrotation+180;
6697                         }
6698
6699                         facing=0;
6700                         facing.z=-1;
6701
6702                         flatfacing=DoRotation(facing,0,player[i].rotation+180,0);
6703
6704                         facing=DoRotation(facing,-player[i].lookrotation2,0,0);
6705                         facing=DoRotation(facing,0,0-player[i].lookrotation,0);
6706
6707                         player[i].targetheadrotation=player[i].lookrotation;
6708                         player[i].targetheadrotation2=player[i].lookrotation2;
6709                     }
6710                     if(indialogue!=-1){
6711                         player[i].targetheadrotation=180-roughDirection(participantfacing[whichdialogue][indialogue][i]);
6712                         player[i].targetheadrotation2=pitch(participantfacing[whichdialogue][indialogue][i]);
6713                     }
6714
6715                     bool pause;
6716
6717                     if(leveltime<.5)
6718                         numenvsounds=0;
6719
6720                     player[i].avoidsomething=0;
6721
6722                     //avoid flaming things
6723                     for(int j=0;j<objects.numobjects;j++)
6724                         if(objects.onfire[j])
6725                             if(findDistancefast(&player[i].coords,&objects.position[j])<sq(objects.scale[j])*200)
6726                                 if(     findDistancefast(&player[i].coords,&objects.position[j])<
6727                                         findDistancefast(&player[i].coords,&player[0].coords)){
6728                                     player[i].collided=0;
6729                                     player[i].avoidcollided=1;
6730                                     if(player[i].avoidsomething==0||
6731                                             findDistancefast(&player[i].coords,&objects.position[j])<
6732                                             findDistancefast(&player[i].coords,&player[i].avoidwhere)){
6733                                         player[i].avoidwhere=objects.position[j];
6734                                         player[i].avoidsomething=1;
6735                                     }
6736                                 }
6737
6738                     //avoid flaming players
6739                     for(int j=0;j<numplayers;j++)
6740                         if(player[j].onfire)
6741                             if(findDistancefast(&player[j].coords,&player[i].coords)<sq(0.3)*200)
6742                                 if(     findDistancefast(&player[i].coords,&player[j].coords)<
6743                                         findDistancefast(&player[i].coords,&player[0].coords)){
6744                                     player[i].collided=0;
6745                                     player[i].avoidcollided=1;
6746                                     if(player[i].avoidsomething==0||
6747                                             findDistancefast(&player[i].coords,&player[j].coords)<
6748                                             findDistancefast(&player[i].coords,&player[i].avoidwhere)){
6749                                         player[i].avoidwhere=player[j].coords;
6750                                         player[i].avoidsomething=1;
6751                                     }
6752                                 }
6753
6754                     if(player[i].collided>.8)
6755                         player[i].avoidcollided=0;
6756
6757                     doAI(i);
6758
6759                     if(animation[player[i].targetanimation].attack==reversed){
6760                         //player[i].targetrotation=player[i].rotation;
6761                         player[i].forwardkeydown=0;
6762                         player[i].leftkeydown=0;
6763                         player[i].backkeydown=0;
6764                         player[i].rightkeydown=0;
6765                         player[i].jumpkeydown=0;
6766                         player[i].attackkeydown=0;
6767                         //player[i].crouchkeydown=0;
6768                         player[i].throwkeydown=0;
6769                     }
6770
6771                     if(indialogue!=-1){
6772                         player[i].forwardkeydown=0;
6773                         player[i].leftkeydown=0;
6774                         player[i].backkeydown=0;
6775                         player[i].rightkeydown=0;
6776                         player[i].jumpkeydown=0;
6777                         player[i].crouchkeydown=0;
6778                         player[i].drawkeydown=0;
6779                         player[i].throwkeydown=0;
6780                     }
6781
6782                     if(player[i].collided<-.3)
6783                         player[i].collided=-.3;
6784                     if(player[i].collided>1)
6785                         player[i].collided=1;
6786                     player[i].collided-=multiplier*4;
6787                     player[i].whichdirectiondelay-=multiplier;
6788                     if(player[i].avoidcollided<-.3||player[i].whichdirectiondelay<=0){
6789                         player[i].avoidcollided=-.3;
6790                         player[i].whichdirection=abs(Random()%2);
6791                         player[i].whichdirectiondelay=.4;
6792                     }
6793                     if(player[i].avoidcollided>1)
6794                         player[i].avoidcollided=1;
6795                     player[i].avoidcollided-=multiplier/4;
6796                     if(!player[i].skeleton.free){
6797                         player[i].stunned-=multiplier;
6798                         player[i].surprised-=multiplier;
6799                     }
6800                     if(i!=0&&player[i].surprised<=0&&
6801                             player[i].aitype==attacktypecutoff&&
6802                             !player[i].dead&&
6803                             !player[i].skeleton.free&&
6804                             animation[player[i].targetanimation].attack==neutral)
6805                         numresponded=1;
6806
6807                     if(!player[i].throwkeydown)
6808                         player[i].throwtogglekeydown=0;
6809
6810                     //pick up weapon
6811                     if(player[i].throwkeydown&&!player[i].throwtogglekeydown){
6812                         if(player[i].weaponactive==-1&&
6813                                 player[i].num_weapons<2&&
6814                                 (player[i].isIdle()||
6815                                  player[i].isCrouch()||
6816                                  player[i].targetanimation==sneakanim||
6817                                  player[i].targetanimation==rollanim||
6818                                  player[i].targetanimation==backhandspringanim||
6819                                  player[i].isFlip()||
6820                                  player[i].isFlip()||
6821                                  player[i].aitype!=playercontrolled)){
6822                             for(int j=0;j<weapons.numweapons;j++){
6823                                 if((weapons.velocity[j].x==0&&weapons.velocity[j].y==0&&weapons.velocity[j].z==0||
6824                                             player[i].aitype==playercontrolled)&&
6825                                         weapons.owner[j]==-1&&
6826                                         player[i].weaponactive==-1)
6827                                     if(findDistancefastflat(&player[i].coords,&weapons.position[j])<2){
6828                                         if(findDistancefast(&player[i].coords,&weapons.position[j])<2){
6829                                             if(player[i].isCrouch()||
6830                                                     player[i].targetanimation==sneakanim||
6831                                                     player[i].isRun()||
6832                                                     player[i].isIdle()||
6833                                                     player[i].aitype!=playercontrolled){
6834                                                 player[i].throwtogglekeydown=1;
6835                                                 setAnimation(i,crouchremoveknifeanim);
6836                                                 player[i].targetrotation=roughDirectionTo(player[i].coords,weapons.position[j]);
6837                                                 player[i].hasvictim=0;
6838                                             }
6839                                             if(player[i].targetanimation==rollanim||player[i].targetanimation==backhandspringanim){
6840                                                 player[i].throwtogglekeydown=1;
6841                                                 player[i].hasvictim=0;
6842
6843                                                 if((weapons.velocity[j].x==0&&weapons.velocity[j].y==0&&weapons.velocity[j].z==0||
6844                                                                 player[i].aitype==playercontrolled)&&
6845                                                             weapons.owner[j]==-1||
6846                                                         player[i].victim&&
6847                                                         weapons.owner[j]==player[i].victim->id)
6848                                                     if(findDistancefastflat(&player[i].coords,&weapons.position[j])<2&&player[i].weaponactive==-1)
6849                                                         if(findDistancefast(&player[i].coords,&weapons.position[j])<1||player[i].victim){
6850                                                             if(weapons.type[j]!=staff)
6851                                                                 emit_sound_at(knifedrawsound, player[i].coords, 128.);
6852
6853                                                             player[i].weaponactive=0;
6854                                                             weapons.owner[j]=player[i].id;
6855                                                             if(player[i].num_weapons>0)
6856                                                                 player[i].weaponids[player[i].num_weapons]=player[i].weaponids[0];
6857                                                             player[i].num_weapons++;
6858                                                             player[i].weaponids[0]=j;
6859                                                         }
6860                                             }
6861                                         }else if((player[i].isIdle()||
6862                                                     player[i].isFlip()||
6863                                                     player[i].aitype!=playercontrolled)&&
6864                                                 findDistancefast(&player[i].coords,&weapons.position[j])<5&&
6865                                                 player[i].coords.y<weapons.position[j].y){
6866                                             if(!player[i].isFlip()){
6867                                                 player[i].throwtogglekeydown=1;
6868                                                 setAnimation(i,removeknifeanim);
6869                                                 player[i].targetrotation=roughDirectionTo(player[i].coords,weapons.position[j]);
6870                                             }
6871                                             if(player[i].isFlip()){
6872                                                 player[i].throwtogglekeydown=1;
6873                                                 player[i].hasvictim=0;
6874
6875                                                 for(int k=0;k<weapons.numweapons;k++){
6876                                                     if(player[i].weaponactive==-1)
6877                                                         if((weapons.velocity[k].x==0&&weapons.velocity[k].y==0&&weapons.velocity[k].z==0||
6878                                                                         player[i].aitype==playercontrolled)&&
6879                                                                     weapons.owner[k]==-1||
6880                                                                 player[i].victim&&
6881                                                                  weapons.owner[k]==player[i].victim->id)
6882                                                             if(findDistancefastflat(&player[i].coords,&weapons.position[k])<3&&
6883                                                                     player[i].weaponactive==-1){
6884                                                                 if(weapons.type[k]!=staff)
6885                                                                     emit_sound_at(knifedrawsound, player[i].coords, 128.);
6886
6887                                                                 player[i].weaponactive=0;
6888                                                                 weapons.owner[k]=player[i].id;
6889                                                                 if(player[i].num_weapons>0)
6890                                                                     player[i].weaponids[player[i].num_weapons]=player[i].weaponids[0];
6891                                                                 player[i].num_weapons++;
6892                                                                 player[i].weaponids[0]=k;
6893                                                             }
6894                                                 }
6895                                             }
6896                                         }
6897                                     }
6898                             }
6899                             if(player[i].isCrouch()||
6900                                     player[i].targetanimation==sneakanim||
6901                                     player[i].isRun()||
6902                                     player[i].isIdle()||player[i].targetanimation==rollanim||
6903                                     player[i].targetanimation==backhandspringanim){
6904                                 if(numplayers>1)
6905                                     for(int j=0;j<numplayers;j++){
6906                                         if(player[i].weaponactive==-1)
6907                                             if(j!=i)
6908                                                 if(player[j].num_weapons&&
6909                                                         player[j].skeleton.free&&
6910                                                         findDistancefast(&player[i].coords,&player[j].coords)<2/*&&player[j].dead*/&&
6911                                                         (((player[j].skeleton.forward.y<0&&
6912                                                            player[j].weaponstuckwhere==0)||
6913                                                           (player[j].skeleton.forward.y>0&&
6914                                                            player[j].weaponstuckwhere==1))||
6915                                                          player[j].weaponstuck==-1||
6916                                                          player[j].num_weapons>1)){
6917                                                     if(player[i].targetanimation!=rollanim&&player[i].targetanimation!=backhandspringanim){
6918                                                         player[i].throwtogglekeydown=1;
6919                                                         player[i].victim=&player[j];
6920                                                         player[i].hasvictim=1;
6921                                                         setAnimation(i,crouchremoveknifeanim);
6922                                                         player[i].targetrotation=roughDirectionTo(player[i].coords,player[j].coords);
6923                                                     }
6924                                                     if(player[i].targetanimation==rollanim||player[i].targetanimation==backhandspringanim){
6925                                                         player[i].throwtogglekeydown=1;
6926                                                         player[i].victim=&player[j];
6927                                                         player[i].hasvictim=1;
6928                                                         int k = player[j].weaponids[0];
6929                                                         if(player[i].hasvictim){
6930                                                             bool fleshstuck;
6931                                                             fleshstuck=0;
6932                                                             if(player[i].victim->weaponstuck!=-1){
6933                                                                 if(player[i].victim->weaponids[player[i].victim->weaponstuck]==k){
6934                                                                     fleshstuck=1;
6935                                                                 }
6936                                                             }
6937                                                             if(!fleshstuck){
6938                                                                 if(weapons.type[k]!=staff)
6939                                                                   emit_sound_at(knifedrawsound, player[i].coords, 128.);
6940                                                             }
6941                                                             if(fleshstuck)
6942                                                               emit_sound_at(fleshstabremovesound, player[i].coords, 128.);
6943
6944                                                             player[i].weaponactive=0;
6945                                                             if(weapons.owner[k]!=-1){
6946                                                                 if(player[i].victim->num_weapons==1)player[i].victim->num_weapons=0;
6947                                                                 else player[i].victim->num_weapons=1;
6948
6949                                                                 player[i].victim->skeleton.longdead=0;
6950                                                                 player[i].victim->skeleton.free=1;
6951                                                                 player[i].victim->skeleton.broken=0;
6952
6953                                                                 for(int l=0;l<player[i].victim->skeleton.num_joints;l++){
6954                                                                     player[i].victim->skeleton.joints[l].velchange=0;
6955                                                                     player[i].victim->skeleton.joints[l].locked=0;
6956                                                                 }
6957
6958                                                                 XYZ relative;
6959                                                                 relative=0;
6960                                                                 relative.y=10;
6961                                                                 Normalise(&relative);
6962                                                                 XYZ footvel,footpoint;
6963                                                                 footvel=0;
6964                                                                 footpoint=weapons.position[k];
6965                                                                 if(player[i].victim->weaponstuck!=-1){
6966                                                                     if(player[i].victim->weaponids[player[i].victim->weaponstuck]==k){
6967                                                                         if(bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .8, .3);
6968                                                                         weapons.bloody[k]=2;
6969                                                                         weapons.blooddrip[k]=5;
6970                                                                         player[i].victim->weaponstuck=-1;
6971                                                                         player[i].victim->bloodloss+=2000;
6972                                                                         player[i].victim->DoDamage(2000);
6973                                                                     }
6974                                                                 }
6975                                                                 if(player[i].victim->num_weapons>0){
6976                                                                     if(player[i].victim->weaponstuck!=0&&player[i].victim->weaponstuck!=-1)player[i].victim->weaponstuck=0;
6977                                                                     if(player[i].victim->weaponids[0]==k)
6978                                                                         player[i].victim->weaponids[0]=player[i].victim->weaponids[player[i].victim->num_weapons];
6979                                                                 }
6980
6981                                                                 player[i].victim->weaponactive=-1;
6982
6983                                                                 playerJoint(player[i].victim,abdomen).velocity+=relative*6;
6984                                                                 playerJoint(player[i].victim,neck).velocity+=relative*6;
6985                                                                 playerJoint(player[i].victim,rightshoulder).velocity+=relative*6;
6986                                                                 playerJoint(player[i].victim,leftshoulder).velocity+=relative*6;
6987                                                             }
6988                                                             weapons.owner[k]=i;
6989                                                             if(player[i].num_weapons>0){
6990                                                                 player[i].weaponids[player[i].num_weapons]=player[i].weaponids[0];
6991                                                             }
6992                                                             player[i].num_weapons++;
6993                                                             player[i].weaponids[0]=k;
6994                                                         }
6995                                                     }
6996                                                 }
6997                                     }
6998                             }
6999                         }
7000                         if(player[i].weaponactive!=-1&&player[i].aitype==playercontrolled){
7001                             if(weapons.type[player[i].weaponids[0]]==knife){
7002                                 if(player[i].isIdle()||
7003                                         player[i].isRun()||
7004                                         player[i].isCrouch()||
7005                                         player[i].targetanimation==sneakanim||
7006                                         player[i].isFlip())
7007                                     if(numplayers>1)
7008                                         for(int j=0;j<numplayers;j++){
7009                                             if(i!=j)
7010                                                 if(tutoriallevel!=1||tutorialstage==49)
7011                                                     if(hostile)
7012                                                         if(normaldotproduct(player[i].facing,player[i].coords-player[j].coords)<0&&
7013                                                                 findDistancefast(&player[i].coords,&player[j].coords)<100&&
7014                                                                 findDistancefast(&player[i].coords,&player[j].coords)>1.5&&
7015                                                                 !player[j].skeleton.free&&
7016                                                                 -1==checkcollide(DoRotation(playerJoint(j,head).position,0,player[j].rotation,0)*player[j].scale+player[j].coords,DoRotation(playerJoint(i,head).position,0,player[i].rotation,0)*player[i].scale+player[i].coords)){
7017                                                             if(!player[i].isFlip()){
7018                                                                 player[i].throwtogglekeydown=1;
7019                                                                 player[i].victim=&player[j];
7020                                                                 setAnimation(i,knifethrowanim);
7021                                                                 player[i].targetrotation=roughDirectionTo(player[i].coords,player[j].coords);
7022                                                                 player[i].targettilt2=pitchTo(player[i].coords,player[j].coords);
7023                                                             }
7024                                                             if(player[i].isFlip()){
7025                                                                 if(player[i].weaponactive!=-1){
7026                                                                     player[i].throwtogglekeydown=1;
7027                                                                     player[i].victim=&player[j];
7028                                                                     XYZ aim;
7029                                                                     weapons.owner[player[i].weaponids[0]]=-1;
7030                                                                     aim=player[i].victim->coords+DoRotation(playerJoint(player[i].victim,abdomen).position,0,player[i].victim->rotation,0)*player[i].victim->scale+player[i].victim->velocity*findDistance(&player[i].victim->coords,&player[i].coords)/50-(player[i].coords+DoRotation(playerJoint(i,righthand).position,0,player[i].rotation,0)*player[i].scale);
7031                                                                     Normalise(&aim);
7032
7033                                                                     aim=DoRotation(aim,(float)abs(Random()%30)-15,(float)abs(Random()%30)-15,0);
7034
7035                                                                     weapons.velocity[player[i].weaponids[0]]=aim*50;
7036                                                                     weapons.tipvelocity[player[i].weaponids[0]]=aim*50;
7037                                                                     weapons.missed[player[i].weaponids[0]]=0;
7038                                                                     weapons.freetime[player[i].weaponids[0]]=0;
7039                                                                     weapons.firstfree[player[i].weaponids[0]]=1;
7040                                                                     weapons.physics[player[i].weaponids[0]]=0;
7041                                                                     player[i].num_weapons--;
7042                                                                     if(player[i].num_weapons){
7043                                                                         player[i].weaponids[0]=player[i].weaponids[player[i].num_weapons];
7044                                                                     }
7045                                                                     player[i].weaponactive=-1;
7046                                                                 }
7047                                                             }
7048                                                         }
7049                                         }
7050                             }
7051                         }
7052                         if(player[i].weaponactive!=-1&&player[i].aitype==playercontrolled){
7053                             if(player[i].isCrouch()||player[i].targetanimation==sneakanim){
7054                                 player[i].throwtogglekeydown=1;
7055                                 weapons.owner[player[i].weaponids[0]]=-1;
7056                                 weapons.velocity[player[i].weaponids[0]]=player[i].velocity*.2;
7057                                 if(weapons.velocity[player[i].weaponids[0]].x==0)weapons.velocity[player[i].weaponids[0]].x=.1;
7058                                 weapons.tipvelocity[player[i].weaponids[0]]=weapons.velocity[player[i].weaponids[0]];
7059                                 weapons.missed[player[i].weaponids[0]]=1;
7060                                 weapons.freetime[player[i].weaponids[0]]=0;
7061                                 weapons.firstfree[player[i].weaponids[0]]=1;
7062                                 weapons.physics[player[i].weaponids[0]]=1;
7063                                 player[i].num_weapons--;
7064                                 if(player[i].num_weapons){
7065                                     player[i].weaponids[0]=player[i].weaponids[player[i].num_weapons];
7066                                     if(player[i].weaponstuck==player[i].num_weapons)player[i].weaponstuck=0;
7067                                 }
7068
7069                                 player[i].weaponactive=-1;
7070                                 for(int j=0;j<numplayers;j++){
7071                                     player[j].wentforweapon=0;
7072                                 }
7073                             }
7074                         }
7075
7076                     }
7077
7078                     //draw weapon
7079                     if(i==0||!player[0].dead||player[i].weaponactive!=-1)
7080                         if(player[i].drawkeydown&&!player[i].drawtogglekeydown||
7081                                 player[i].num_weapons==2&&
7082                                 player[i].weaponactive==-1&&
7083                                 player[i].isIdle()||
7084                                 player[0].dead&&
7085                                 player[i].weaponactive!=-1&&
7086                                 i!=0){
7087                             bool isgood=1;
7088                             if(player[i].weaponactive!=-1)
7089                                 if(weapons.type[player[i].weaponids[player[i].weaponactive]]==staff)
7090                                     isgood=0;
7091                             if(isgood&&player[i].creature!=wolftype){
7092                                 if(player[i].isIdle()&&player[i].num_weapons&&weapons.type[player[i].weaponids[0]]==knife){
7093                                     setAnimation(i,drawrightanim);
7094                                     player[i].drawtogglekeydown=1;
7095                                 }
7096                                 if((player[i].isIdle()||
7097                                             (player[i].aitype!=playercontrolled&&
7098                                              player[0].weaponactive!=-1&&
7099                                              player[i].isRun()))&&
7100                                         player[i].num_weapons&&
7101                                         weapons.type[player[i].weaponids[0]]==sword){
7102                                     setAnimation(i,drawleftanim);
7103                                     player[i].drawtogglekeydown=1;
7104                                 }
7105                                 if(player[i].isCrouch()&&player[i].num_weapons&&weapons.type[player[i].weaponids[0]]==knife){
7106                                     setAnimation(i,crouchdrawrightanim);
7107                                     player[i].drawtogglekeydown=1;
7108                                 }
7109                             }
7110                         }
7111                     //clean weapon
7112                     if(player[i].isCrouch()&&
7113                             weapons.bloody[player[i].weaponids[player[i].weaponactive]]&&
7114                             bloodtoggle&&
7115                             player[i].onterrain&&
7116                             player[i].num_weapons&&
7117                             player[i].weaponactive!=-1&&
7118                             player[i].attackkeydown){
7119                         if(weapons.bloody[player[i].weaponids[player[i].weaponactive]]&&
7120                                 player[i].onterrain&&
7121                                 bloodtoggle&&musictype!=stream_music2){
7122                             if(weapons.type[player[i].weaponids[player[i].weaponactive]]==knife)
7123                                 setAnimation(i,crouchstabanim);
7124                             if(weapons.type[player[i].weaponids[player[i].weaponactive]]==sword)
7125                                 setAnimation(i,swordgroundstabanim);
7126                             player[i].hasvictim=0;
7127                             //player[i].attacktogglekeydown=1;
7128                         }
7129                     }
7130
7131                     if(!player[i].drawkeydown)
7132                         player[i].drawtogglekeydown=0;
7133
7134                     XYZ absflatfacing;
7135                     if(i==0){
7136                         absflatfacing=0;
7137                         absflatfacing.z=-1;
7138
7139                         absflatfacing=DoRotation(absflatfacing,0,-rotation,0);
7140                     }
7141                     else absflatfacing=flatfacing;
7142
7143                     if(indialogue!=-1){
7144                         player[i].forwardkeydown=0;
7145                         player[i].leftkeydown=0;
7146                         player[i].backkeydown=0;
7147                         player[i].rightkeydown=0;
7148                         player[i].jumpkeydown=0;
7149                         player[i].crouchkeydown=0;
7150                         player[i].drawkeydown=0;
7151                         player[i].throwkeydown=0;
7152                     }
7153                     movekey=0;
7154                     //Do controls
7155                     if(!animation[player[i].targetanimation].attack&&
7156                             player[i].targetanimation!=staggerbackhighanim&&
7157                             player[i].targetanimation!=staggerbackhardanim&&
7158                             player[i].targetanimation!=backhandspringanim&&
7159                             player[i].targetanimation!=dodgebackanim){
7160                         if(!player[i].forwardkeydown)
7161                             player[i].forwardstogglekeydown=0;
7162                         if(player[i].crouchkeydown){
7163                             //Crouch
7164                             target=-2;
7165                             if(i==0){
7166                                 player[i].superruntoggle=1;
7167                                 if(numplayers>1)
7168                                     for(int j=0;j<numplayers;j++)
7169                                         if(j!=i&&!player[j].skeleton.free&&player[j].aitype==passivetype)
7170                                             if(findDistancefast(&player[j].coords,&player[i].coords)<16)
7171                                                 player[i].superruntoggle=0;
7172                             }
7173
7174                             if(numplayers>1)
7175                                 for(int j=0;j<numplayers;j++){
7176                                     if(j!=i&&!player[j].skeleton.free&&player[j].victim&&player[i].lowreversaldelay<=0){
7177                                         if(findDistancefast(&player[j].coords,&player[j].victim->coords)<3&&
7178                                                 player[j].victim==&player[i]&&
7179                                                 (player[j].targetanimation==sweepanim||
7180                                                  player[j].targetanimation==upunchanim||
7181                                                  player[j].targetanimation==wolfslapanim||
7182                                                  ((player[j].targetanimation==swordslashanim||
7183                                                    player[j].targetanimation==knifeslashstartanim||
7184                                                    player[j].targetanimation==staffhitanim||
7185                                                    player[j].targetanimation==staffspinhitanim)&&
7186                                                   findDistancefast(&player[j].coords,&player[i].coords)<2))){
7187                                             if(target>=0)
7188                                                 target=-1;
7189                                             else
7190                                                 target=j;
7191                                         }
7192                                     }
7193                                 }
7194                             if(target>=0)
7195                                 player[target].Reverse();
7196                             player[i].lowreversaldelay=.5;
7197
7198                             if(player[i].isIdle()){
7199                                 setAnimation(i,player[i].getCrouch());
7200                                 player[i].transspeed=10;
7201                             }
7202                             if(player[i].isRun()||
7203                                     (player[i].isStop()&&
7204                                      (player[i].leftkeydown||
7205                                       player[i].rightkeydown||
7206                                       player[i].forwardkeydown||
7207                                       player[i].backkeydown))){
7208                                 setAnimation(i,rollanim);
7209                                 player[i].transspeed=20;
7210                             }
7211                         }
7212                         if(!player[i].crouchkeydown){
7213                             //Uncrouch
7214                             if(!player[i].isRun()&&player[i].targetanimation!=sneakanim&&i==0)player[i].superruntoggle=0;
7215                             target=-2;
7216                             if(player[i].isCrouch()){
7217                                 if(numplayers>1)
7218                                     for(int j=0;j<numplayers;j++){
7219                                         if(j!=i&&
7220                                                 !player[j].skeleton.free&&
7221                                                 player[j].victim&&
7222                                                 player[i].highreversaldelay<=0){
7223                                             if(findDistancefast(&player[j].coords,&player[j].victim->coords)<3&&
7224                                                     player[j].victim==&player[i]&&
7225                                                     (player[j].targetanimation==spinkickanim)&&
7226                                                     player[i].isCrouch()){
7227                                                 if(target>=0)
7228                                                     target=-1;
7229                                                 else
7230                                                     target=j;
7231                                             }
7232                                         }
7233                                     }
7234                                 if(target>=0)
7235                                     player[target].Reverse();
7236                                 player[i].highreversaldelay=.5;
7237
7238                                 if(player[i].isCrouch()){
7239                                     if(!player[i].wasCrouch()){
7240                                         player[i].currentanimation=player[i].getCrouch();
7241                                         player[i].currentframe=0;
7242                                     }
7243                                     setAnimation(i,player[i].getIdle());
7244                                     player[i].transspeed=10;
7245                                 }
7246                             }
7247                             if(player[i].targetanimation==sneakanim){
7248                                 setAnimation(i,player[i].getIdle());
7249                                 player[i].transspeed=10;
7250                             }
7251                         }
7252                         if(player[i].forwardkeydown){
7253                             if(player[i].isIdle()||
7254                                     (player[i].isStop()&&
7255                                      player[i].targetrotation==player[i].rotation)||
7256                                     (player[i].isLanding()&&
7257                                      player[i].targetframe>0&&
7258                                      !player[i].jumpkeydown)||
7259                                     (player[i].isLandhard()&&
7260                                      player[i].targetframe>0&&
7261                                      !player[i].jumpkeydown&&
7262                                      player[i].crouchkeydown)){
7263                                 if(player[i].aitype==passivetype)
7264                                     setAnimation(i,walkanim);
7265                                 else
7266                                     setAnimation(i,player[i].getRun());
7267                             }
7268                             if(player[i].isCrouch()){
7269                                 player[i].targetanimation=sneakanim;
7270                                 if(player[i].wasCrouch())
7271                                     player[i].target=0;
7272                                 player[i].targetframe=0;
7273                             }
7274                             if(player[i].targetanimation==hanganim/*&&(!player[i].forwardstogglekeydown||player[i].aitype!=playercontrolled)*/){
7275                                 setAnimation(i,climbanim);
7276                                 player[i].targetframe=1;
7277                                 player[i].jumpclimb=1;
7278                             }
7279                             if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
7280                                 player[i].velocity+=absflatfacing*5*multiplier;
7281                             }
7282                             player[i].forwardstogglekeydown=1;
7283                             movekey=1;
7284                         }
7285                         if (player[i].rightkeydown){
7286                             if(player[i].isIdle()||
7287                                     (player[i].isStop()&&
7288                                      player[i].targetrotation==player[i].rotation)||
7289                                     (player[i].isLanding()&&
7290                                      player[i].targetframe>0&&
7291                                      !player[i].jumpkeydown)||
7292                                     (player[i].isLandhard()&&
7293                                      player[i].targetframe>0&&
7294                                      !player[i].jumpkeydown&&
7295                                      player[i].crouchkeydown)){
7296                                 setAnimation(i,player[i].getRun());
7297                             }
7298                             if(player[i].isCrouch()){
7299                                 player[i].targetanimation=sneakanim;
7300                                 if(player[i].wasCrouch())
7301                                     player[i].target=0;
7302                                 player[i].targetframe=0;
7303                             }
7304                             if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
7305                                 player[i].velocity+=DoRotation(absflatfacing*5*multiplier,0,-90,0);
7306                             }
7307                             player[i].targetrotation-=90;
7308                             if(player[i].forwardkeydown)player[i].targetrotation+=45;
7309                             if(player[i].backkeydown)player[i].targetrotation-=45;
7310                             movekey=1;
7311                         }
7312                         if ( player[i].leftkeydown){
7313                             if(player[i].isIdle()||
7314                                     (player[i].isStop()&&
7315                                      player[i].targetrotation==player[i].rotation)||
7316                                     (player[i].isLanding()&&
7317                                      player[i].targetframe>0&&
7318                                      !player[i].jumpkeydown)||
7319                                     (player[i].isLandhard()&&
7320                                      player[i].targetframe>0&&
7321                                      !player[i].jumpkeydown&&
7322                                      player[i].crouchkeydown)){
7323                                 setAnimation(i,player[i].getRun());
7324                             }
7325                             if(player[i].isCrouch()){
7326                                 player[i].targetanimation=sneakanim;
7327                                 if(player[i].wasCrouch())
7328                                     player[i].target=0;
7329                                 player[i].targetframe=0;
7330                             }
7331                             if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
7332                                 player[i].velocity-=DoRotation(absflatfacing*5*multiplier,0,-90,0);
7333                             }
7334                             player[i].targetrotation+=90;
7335                             if(player[i].forwardkeydown)player[i].targetrotation-=45;
7336                             if(player[i].backkeydown)player[i].targetrotation+=45;
7337                             movekey=1;
7338                         }
7339                         if(player[i].backkeydown){
7340                             if(player[i].isIdle()||
7341                                     (player[i].isStop()&&
7342                                      player[i].targetrotation==player[i].rotation)||
7343                                     (player[i].isLanding()&&
7344                                      player[i].targetframe>0&&
7345                                      !player[i].jumpkeydown)||
7346                                     (player[i].isLandhard()&&
7347                                      player[i].targetframe>0&&
7348                                      !player[i].jumpkeydown&&
7349                                      player[i].crouchkeydown)){
7350                                 setAnimation(i,player[i].getRun());
7351                             }
7352                             if(player[i].isCrouch()){
7353                                 player[i].targetanimation=sneakanim;
7354                                 if(player[i].wasCrouch())
7355                                     player[i].target=0;
7356                                 player[i].targetframe=0;
7357                             }
7358                             if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
7359                                 player[i].velocity-=absflatfacing*5*multiplier;
7360                             }
7361                             if(player[i].targetanimation==hanganim){
7362                                 player[i].currentanimation=jumpdownanim;
7363                                 player[i].targetanimation=jumpdownanim;
7364                                 player[i].target=0;
7365                                 player[i].currentframe=0;
7366                                 player[i].targetframe=1;
7367                                 player[i].velocity=0;
7368                                 player[i].velocity.y+=gravity;
7369                                 player[i].coords.y-=1.4;
7370                                 player[i].grabdelay=1;
7371                             }
7372                             if ( !player[i].leftkeydown&&!player[i].rightkeydown)
7373                                 player[i].targetrotation+=180;
7374                             movekey=1;
7375                         }
7376                         if((player[i].jumpkeydown&&!player[i].jumpclimb)||player[i].jumpstart){
7377                             if((((player[i].isLanding()&&player[i].targetframe>=3)||
7378                                             player[i].isRun()||
7379                                             player[i].targetanimation==walkanim||
7380                                             player[i].isCrouch()||
7381                                             player[i].targetanimation==sneakanim)&&
7382                                         player[i].jumppower>1)&&
7383                                     ((player[i].targetanimation!=rabbitrunninganim&&
7384                                       player[i].targetanimation!=wolfrunninganim)||i!=0)){
7385                                 player[i].jumpstart=0;
7386                                 setAnimation(i,jumpupanim);
7387                                 player[i].rotation=player[i].targetrotation;
7388                                 player[i].transspeed=20;
7389                                 player[i].FootLand(0,1);
7390                                 player[i].FootLand(1,1);
7391
7392                                 facing=0;
7393                                 facing.z=-1;
7394                                 flatfacing=DoRotation(facing,0,player[i].targetrotation+180,0);
7395
7396                                 if(movekey)player[i].velocity=flatfacing*player[i].speed*45*player[i].scale;
7397                                 if(!movekey)player[i].velocity=0;
7398
7399                                 //Dodge sweep?
7400                                 target=-2;
7401                                 if(numplayers>1)
7402                                     for(int j=0;j<numplayers;j++){
7403                                         if(j!=i&&!player[j].skeleton.free&&player[j].victim){
7404                                             if(findDistancefast(&player[j].coords,&player[j].victim->coords)<3&&
7405                                                     player[j].victim==&player[i]&&
7406                                                     (player[j].targetanimation==sweepanim)){
7407                                                 if(target>=0)target=-1;
7408                                                 else target=j;
7409                                             }
7410                                         }
7411                                     }
7412                                     if(target>=0)player[i].velocity.y=1;
7413                                     else if(player[i].crouchkeydown||player[i].aitype!=playercontrolled){
7414                                         player[i].velocity.y=7;
7415                                         player[i].crouchtogglekeydown=1;
7416                                     }
7417                                     else player[i].velocity.y=5;
7418
7419                                     if(mousejump&&i==0&&debugmode){
7420                                         if(!player[i].isLanding())player[i].tempdeltav=deltav;
7421                                         if(player[i].tempdeltav<0)player[i].velocity.y-=(float)(player[i].tempdeltav)/multiplier/1000;
7422                                     }
7423
7424                                     player[i].coords.y+=.2;
7425                                     player[i].jumppower-=1;
7426
7427                                     if (!i)
7428                                       emit_sound_at(whooshsound, player[i].coords, 128.);
7429
7430                                     emit_sound_at(jumpsound, player[i].coords, 128.);
7431                             }
7432                             if((player[i].isIdle())&&player[i].jumppower>1){
7433                                 setAnimation(i,player[i].getLanding());
7434                                 player[i].targetframe=2;
7435                                 player[i].landhard=0;
7436                                 player[i].jumpstart=1;
7437                                 player[i].tempdeltav=deltav;
7438                             }
7439                             if(player[i].targetanimation==jumpupanim&&
7440                                     (((!floatjump&&
7441                                        !editorenabled)||
7442                                       !debugmode)||
7443                                      player[i].aitype!=playercontrolled)){
7444                                 if(player[i].jumppower>multiplier*6){
7445                                     player[i].velocity.y+=multiplier*6;
7446                                     player[i].jumppower-=multiplier*6;
7447                                 }
7448                                 if(player[i].jumppower<=multiplier*6){
7449                                     player[i].velocity.y+=player[i].jumppower;
7450                                     player[i].jumppower=0;
7451                                 }
7452                             }
7453                             if(((floatjump||editorenabled)&&debugmode)&&i==0)player[i].velocity.y+=multiplier*30;
7454                         }
7455
7456                         if(!movekey){
7457                             if(player[i].isRun()||player[i].targetanimation==walkanim)
7458                                 setAnimation(i,player[i].getStop());
7459                             if(player[i].targetanimation==sneakanim){
7460                                 player[i].targetanimation=player[i].getCrouch();
7461                                 if(player[i].currentanimation==sneakanim)
7462                                     player[i].target=0;
7463                                 player[i].targetframe=0;
7464                             }
7465                         }
7466                         if(player[i].targetanimation==walkanim&&
7467                                 (player[i].aitype==attacktypecutoff||
7468                                  player[i].aitype==searchtype||
7469                                  (player[i].aitype==passivetype&&
7470                                   player[i].numwaypoints<=1)))
7471                             setAnimation(i,player[i].getStop());
7472                         if(player[i].isRun()&&(player[i].aitype==passivetype))
7473                             setAnimation(i,player[i].getStop());
7474                     }
7475                 }
7476                 if(player[i].targetanimation==rollanim)
7477                     player[i].targetrotation=oldtargetrotation;
7478             }
7479
7480             //Rotation
7481             for(int k=0;k<numplayers;k++){
7482                 if(fabs(player[k].rotation-player[k].targetrotation)>180){
7483                     if(player[k].rotation>player[k].targetrotation)
7484                         player[k].rotation-=360;
7485                     else
7486                         player[k].rotation+=360;
7487                 }
7488
7489                 //stop to turn in right direction
7490                 if(fabs(player[k].rotation-player[k].targetrotation)>90&&(player[k].isRun()||player[k].targetanimation==walkanim))
7491                     setAnimation(k,player[k].getStop());
7492
7493                 if(player[k].targetanimation==backhandspringanim||player[k].targetanimation==dodgebackanim)
7494                     player[k].targettilt=0;
7495
7496                 if(player[k].targetanimation!=jumpupanim&&
7497                         player[k].targetanimation!=backhandspringanim&&
7498                         player[k].targetanimation!=jumpdownanim&&
7499                         !player[k].isFlip()){
7500                     player[k].targettilt=0;
7501                     if(player[k].jumppower<0&&!player[k].jumpkeydown)
7502                         player[k].jumppower=0;
7503                     player[k].jumppower+=multiplier*7;
7504                     if(player[k].isCrouch())
7505                         player[k].jumppower+=multiplier*7;
7506                     if(player[k].jumppower>5)
7507                         player[k].jumppower=5;
7508                 }
7509
7510                 if(player[k].isRun())
7511                     player[k].targettilt=(player[k].rotation-player[k].targetrotation)/4;
7512
7513                 player[k].tilt=stepTowardf(player[k].tilt,player[k].targettilt,multiplier*150);
7514                 player[k].grabdelay-=multiplier;
7515             }
7516
7517             //do animations
7518             for(int k=0;k<numplayers;k++){
7519                 player[k].DoAnimations();
7520                 player[k].whichpatchx=player[k].coords.x/(terrain.size/subdivision*terrain.scale);
7521                 player[k].whichpatchz=player[k].coords.z/(terrain.size/subdivision*terrain.scale);
7522             }
7523
7524             //do stuff
7525             objects.DoStuff();
7526             
7527             for(int j=numenvsounds-1;j>=0;j--){
7528                 envsoundlife[j]-=multiplier;
7529                 if(envsoundlife[j]<0){
7530                     numenvsounds--;
7531                     envsoundlife[j]=envsoundlife[numenvsounds];
7532                     envsound[j]=envsound[numenvsounds];
7533                 }
7534             }
7535             if(slomo)
7536                 OPENAL_SetFrequency(OPENAL_ALL, slomofreq);
7537             else
7538                 OPENAL_SetFrequency(OPENAL_ALL, 22050);
7539
7540             if(tutoriallevel==1){
7541                 XYZ temp;
7542                 XYZ temp2;
7543                 XYZ temp3;
7544                 XYZ oldtemp;
7545                 XYZ oldtemp2;
7546                 temp.x=1011;
7547                 temp.y=84;
7548                 temp.z=491;
7549                 temp2.x=1025;
7550                 temp2.y=75;
7551                 temp2.z=447;
7552                 temp3.x=1038;
7553                 temp3.y=76;
7554                 temp3.z=453;
7555                 oldtemp=temp;
7556                 oldtemp2=temp2;
7557                 if(tutorialstage>=51)
7558                     if(findDistancefast(&temp,&player[0].coords)>=findDistancefast(&temp,&temp2)-1||findDistancefast(&temp3,&player[0].coords)<4){
7559                         OPENAL_StopSound(OPENAL_ALL);  // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
7560                         OPENAL_SetFrequency(OPENAL_ALL, 0.001);
7561
7562                         emit_stream_np(stream_music3);
7563
7564                         gameon=0;
7565                         mainmenu=5;
7566
7567                         fireSound();
7568
7569                         flash();
7570                     }
7571                 if(tutorialstage<51)
7572                     if(findDistancefast(&temp,&player[0].coords)>=findDistancefast(&temp,&temp2)-1||findDistancefast(&temp3,&player[0].coords)<4){
7573                         emit_sound_at(fireendsound, player[0].coords);
7574
7575                         player[0].coords=(oldtemp+oldtemp2)/2;
7576
7577                         flash();
7578                     }
7579                 if(tutorialstage>=14&&tutorialstage<50)
7580                     if(findDistancefast(&temp,&player[1].coords)>=findDistancefast(&temp,&temp2)-1||findDistancefast(&temp3,&player[1].coords)<4){
7581                         emit_sound_at(fireendsound, player[1].coords);
7582
7583                         for(int i=0;i<player[1].skeleton.num_joints;i++){
7584                             if(Random()%2==0){
7585                                 if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
7586                                 if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
7587                                 if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
7588                                 if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
7589                                 Sprite::MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
7590                             }
7591                         }
7592
7593                         player[1].coords=(oldtemp+oldtemp2)/2;
7594                         for(int i=0;i<player[1].skeleton.num_joints;i++){
7595                             player[1].skeleton.joints[i].velocity=0;
7596                             if(Random()%2==0){
7597                                 if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
7598                                 if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
7599                                 if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
7600                                 if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
7601                                 Sprite::MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
7602                             }
7603                         }
7604                     }
7605             }
7606
7607
7608             //3d sound
7609             static float gLoc[3];
7610             gLoc[0]=viewer.x;
7611             gLoc[1]=viewer.y;
7612             gLoc[2]=viewer.z;
7613             static float vel[3];
7614             vel[0]=(viewer.x-oldviewer.x)/multiplier;
7615             vel[1]=(viewer.y-oldviewer.y)/multiplier;
7616             vel[2]=(viewer.z-oldviewer.z)/multiplier;
7617
7618             //Set orientation with forward and up vectors
7619             static XYZ upvector;
7620             upvector=0;
7621             upvector.z=-1;
7622
7623             upvector=DoRotation(upvector,-rotation2+90,0,0);
7624             upvector=DoRotation(upvector,0,0-rotation,0);
7625
7626             facing=0;
7627             facing.z=-1;
7628
7629             facing=DoRotation(facing,-rotation2,0,0);
7630             facing=DoRotation(facing,0,0-rotation,0);
7631
7632
7633             static float ori[6];
7634             ori[0] = -facing.x;
7635             ori[1] = facing.y;
7636             ori[2] = -facing.z;
7637             ori[3] = -upvector.x;
7638             ori[4] = upvector.y;
7639             ori[5] = -upvector.z;
7640
7641             OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
7642             OPENAL_Update();
7643
7644             oldviewer=viewer;
7645                 }
7646         }
7647
7648         if(Input::isKeyPressed(SDLK_F1))
7649                 Screenshot();
7650 }
7651
7652
7653
7654 void    Game::TickOnce(){
7655         if(mainmenu)
7656                 rotation+=multiplier*5;
7657         else
7658                 if(directing||indialogue==-1) {
7659                         rotation+=deltah*.7;
7660                         if(!invertmouse)
7661                 rotation2+=deltav*.7;
7662                         if(invertmouse)
7663                 rotation2-=deltav*.7;
7664                         if(rotation2>90)
7665                 rotation2=90;
7666                         if(rotation2<-70)
7667                 rotation2=-70;
7668                 }
7669 }
7670
7671 void    Game::TickOnceAfter(){
7672         static XYZ colviewer;
7673         static XYZ coltarget;
7674         static XYZ target;
7675         static XYZ col;
7676         static float brotate;
7677         static XYZ facing;
7678         static float changedelay;
7679         static bool alldead;
7680         static float unseendelay;
7681         static float cameraspeed;
7682
7683         if(!mainmenu){
7684
7685                 if(environment==snowyenvironment)
7686             music1=stream_music1snow;
7687                 if(environment==grassyenvironment)
7688             music1=stream_music1grass;
7689                 if(environment==desertenvironment)
7690             music1=stream_music1desert;
7691
7692                 realthreat=0;
7693
7694                 musictype=music1;
7695                 for(int i=0;i<numplayers;i++){
7696                         if((player[i].aitype==attacktypecutoff||
7697                         player[i].aitype==getweapontype||
7698                         player[i].aitype==gethelptype||
7699                         player[i].aitype==searchtype)&&
7700                     !player[i].dead/*&&player[i].surprised<=0*/&&
7701                     (player[i].targetanimation!=sneakattackedanim&&
7702                      player[i].targetanimation!=knifesneakattackedanim&&
7703                      player[i].targetanimation!=swordsneakattackedanim)){
7704                                 musictype=stream_music2;
7705                                 realthreat=1;
7706                         }
7707                 }
7708                 if(player[0].dead)
7709             musictype=stream_music3;
7710
7711
7712                 if(musictype==stream_music2)
7713                         unseendelay=1;
7714
7715                 if(oldmusictype==stream_music2&&musictype!=stream_music2){
7716                         unseendelay-=multiplier;
7717                         if(unseendelay>0)
7718                                 musictype=stream_music2;
7719                 }
7720
7721
7722                 if(loading==2){
7723                         musictype=stream_music3;
7724                         musicvolume[2]=512;
7725                         musicvolume[0]=0;
7726                         musicvolume[1]=0;
7727                         musicvolume[3]=0;
7728                 }
7729
7730                 if(musictoggle)
7731                         if(musictype!=oldmusictype&&musictype==stream_music2)
7732                                 emit_sound_np(alarmsound);
7733                 musicselected=musictype;
7734
7735                 if(musicselected==music1)
7736             musicvolume[0]+=multiplier*450;
7737                 else
7738             musicvolume[0]-=multiplier*450;
7739                 if(musicselected==stream_music2)
7740             musicvolume[1]+=multiplier*450;
7741                 else
7742             musicvolume[1]-=multiplier*450;
7743                 if(musicselected==stream_music3)
7744             musicvolume[2]+=multiplier*450;
7745                 else
7746             musicvolume[2]-=multiplier*450;
7747
7748                 for(int i=0;i<3;i++){
7749                         if(musicvolume[i]<0)
7750                 musicvolume[i]=0;
7751                         if(musicvolume[i]>512)
7752                 musicvolume[i]=512;
7753                 }
7754
7755                 if(musicvolume[2]>128&&!loading&&!mainmenu)
7756             musicvolume[2]=128;
7757
7758                 if(musictoggle){
7759                         if(musicvolume[0]>0&&oldmusicvolume[0]<=0)
7760                           emit_stream_np(music1, musicvolume[0]);
7761                         if(musicvolume[1]>0&&oldmusicvolume[1]<=0)
7762                           emit_stream_np(stream_music2, musicvolume[1]);
7763                         if(musicvolume[2]>0&&oldmusicvolume[2]<=0)
7764                           emit_stream_np(stream_music3, musicvolume[2]);
7765                         if(musicvolume[0]<=0&&oldmusicvolume[0]>0)
7766                                 pause_sound(music1);
7767                         if(musicvolume[1]<=0&&oldmusicvolume[1]>0)
7768                                 pause_sound(stream_music2);
7769                         if(musicvolume[2]<=0&&oldmusicvolume[2]>0)
7770                                 pause_sound(stream_music3);
7771
7772                         if(musicvolume[0]!=oldmusicvolume[0])
7773                                 OPENAL_SetVolume(channels[music1], musicvolume[0]);
7774                         if(musicvolume[1]!=oldmusicvolume[1])
7775                                 OPENAL_SetVolume(channels[stream_music2], musicvolume[1]);
7776                         if(musicvolume[2]!=oldmusicvolume[2])
7777                                 OPENAL_SetVolume(channels[stream_music3], musicvolume[2]);
7778
7779                         for(int i=0;i<3;i++)
7780                                 oldmusicvolume[i]=musicvolume[i];
7781                 } else {
7782                         pause_sound(music1);
7783                         pause_sound(stream_music2);
7784                         pause_sound(stream_music3);
7785
7786                         for(int i=0;i<4;i++){
7787                                 oldmusicvolume[i]=0;
7788                                 musicvolume[i]=0;
7789                         }
7790                 }
7791
7792                 killhotspot=2;
7793                 for(int i=0;i<numhotspots;i++){
7794                         if(hotspottype[i]>10&&hotspottype[i]<20){
7795                                 if(player[hotspottype[i]-10].dead==0)
7796                                         killhotspot=0;
7797                                 else if(killhotspot==2)
7798                                         killhotspot=1;
7799                         }
7800                 }
7801                 if(killhotspot==2)
7802             killhotspot=0;
7803
7804
7805                 winhotspot=0;
7806                 for(int i=0;i<numhotspots;i++)
7807                         if(hotspottype[i]==-1)
7808                                 if(findDistancefast(&player[0].coords,&hotspot[i])<hotspotsize[i])
7809                                         winhotspot=1;
7810
7811                 int numalarmed=0;
7812                 for(int i=1;i<numplayers;i++)
7813                         if(!player[i].dead&&player[i].aitype==attacktypecutoff&&player[i].surprised<=0)
7814                 numalarmed++;
7815                 if(numalarmed>maxalarmed)
7816             maxalarmed=numalarmed;
7817
7818                 if(changedelay<=0&&!loading&&!editorenabled&&gameon&&!tutoriallevel&&changedelay!=-999&&!won){
7819                         if(player[0].dead&&changedelay<=0){
7820                                 changedelay=1;
7821                                 targetlevel=whichlevel;
7822                         }
7823                         alldead=1;
7824                         for(int i=1;i<numplayers;i++)
7825                                 if(!player[i].dead&&player[i].howactive<typedead1)
7826                     alldead=0;
7827
7828
7829                         if(alldead&&!player[0].dead&&maptype==mapkilleveryone){
7830                                 changedelay=1;
7831                                 targetlevel=whichlevel+1;
7832                                 if(targetlevel>numchallengelevels-1)targetlevel=0;
7833                         }
7834                         if(winhotspot||windialogue){
7835                                 changedelay=0.1;
7836                                 targetlevel=whichlevel+1;
7837                                 if(targetlevel>numchallengelevels-1)targetlevel=0;
7838                         }
7839
7840
7841                         if(killhotspot){
7842                                 changedelay=1;
7843                                 targetlevel=whichlevel+1;
7844                                 if(targetlevel>numchallengelevels-1)targetlevel=0;
7845                         }
7846
7847                         if(changedelay>0&&!player[0].dead&&!won){
7848                                 //high scores, awards, win
7849                                 if(campaign){
7850                                         accountactive->winCampaignLevel(whichchoice, bonustotal, leveltime);
7851                                         scoreadded=1;
7852                                 }else{
7853                                         accountactive->winLevel(whichlevel,bonustotal-startbonustotal,leveltime);
7854                                 }
7855                                 won=1;
7856                         }
7857                 }
7858
7859                 if(!winfreeze){
7860
7861                         if(leveltime<1){
7862                                 loading=0;
7863                                 changedelay=.1;
7864                                 alldead=0;
7865                                 winhotspot=0;
7866                                 killhotspot=0;
7867                         }
7868
7869                         if(!editorenabled&&gameon&&!mainmenu){
7870                                 if(changedelay!=-999)
7871                     changedelay-=multiplier/7;
7872                                 if(player[0].dead)
7873                     targetlevel=whichlevel;
7874                                 if(loading==2&&!campaign){
7875                                         flash();
7876
7877                                         fireSound(firestartsound);
7878
7879                                         if(!player[0].dead&&targetlevel!=whichlevel)
7880                                                 startbonustotal=bonustotal;
7881                                         if(player[0].dead)
7882                         Loadlevel(whichlevel);
7883                                         else
7884                         Loadlevel(targetlevel);
7885
7886                                         fireSound();
7887
7888                                         loading=3;
7889                                 }
7890                                 if(loading==2&&targetlevel==whichlevel){
7891                                         flash();
7892                                         loadtime=0;
7893
7894                                         fireSound(firestartsound);
7895
7896                                         Loadlevel(campaignmapname[levelorder[accountactive->getCampaignChoicesMade()]]);
7897
7898                                         fireSound();
7899
7900                                         loading=3;
7901                                 }
7902                                 if(changedelay<=-999&&
7903                         whichlevel!=-2&&
7904                         !loading&&
7905                         (player[0].dead||
7906                          (alldead&&maptype==mapkilleveryone)||
7907                          (winhotspot)||
7908                          (killhotspot))&&
7909                         !winfreeze)
7910                     loading=1;
7911                                 if((player[0].dead||
7912                             (alldead&&maptype==mapkilleveryone)||
7913                             (winhotspot)||
7914                             (windialogue)||
7915                             (killhotspot))&&
7916                         changedelay<=0){
7917                     if(whichlevel!=-2&&!loading&&!player[0].dead){
7918                         winfreeze=1;
7919                         changedelay=-999;
7920                     }
7921                     if(player[0].dead)
7922                         loading=1;
7923                                 }
7924                         }
7925
7926                         if(campaign)
7927                                 if(mainmenu==0&&winfreeze&&(campaignchoosenext[campaignchoicewhich[whichchoice]])==1)
7928                                         if(campaignnumnext[campaignchoicewhich[whichchoice]]==0)
7929                                                 endgame=1;
7930                                 else if(mainmenu==0&&winfreeze){
7931                                         if(campaignchoosenext[campaignchoicewhich[whichchoice]]==2)
7932                                                 stealthloading=1;
7933                                         else
7934                         stealthloading=0;
7935
7936                                         if(!stealthloading){
7937                                                 float gLoc[3]={0,0,0};
7938                                                 float vel[3]={0,0,0};
7939                                                 fireSound(firestartsound);
7940
7941                                                 flash();
7942                                         }
7943
7944                                         startbonustotal=0;
7945
7946                                         ifstream ipstream(ConvertFileName(":Data:Campaigns:main.txt"));
7947                                         ipstream.ignore(256,':');
7948                                         ipstream >> campaignnumlevels;
7949                                         for(int i=0;i<campaignnumlevels;i++){
7950                                                 ipstream.ignore(256,':');
7951                                                 ipstream.ignore(256,':');
7952                                                 ipstream.ignore(256,' ');
7953                                                 ipstream >> campaignmapname[i];
7954                                                 ipstream.ignore(256,':');
7955                                                 ipstream >> campaigndescription[i];
7956                                                 for(int j=0;j<256;j++){
7957                                                         if(campaigndescription[i][j]=='_')campaigndescription[i][j]=' ';
7958                                                 }
7959                                                 ipstream.ignore(256,':');
7960                                                 ipstream >> campaignchoosenext[i];
7961                                                 ipstream.ignore(256,':');
7962                                                 ipstream >> campaignnumnext[i];
7963                                                 for(int j=0;j<campaignnumnext[i];j++){
7964                                                         ipstream.ignore(256,':');
7965                                                         ipstream >> campaignnextlevel[i][j];
7966                                                         campaignnextlevel[i][j]-=1;
7967                                                 }
7968                                                 ipstream.ignore(256,':');
7969                                                 ipstream >> campaignlocationx[i];
7970                                                 ipstream.ignore(256,':');
7971                                                 ipstream >> campaignlocationy[i];
7972                                         }
7973                                         ipstream.close();
7974
7975                                         for(int i=0;i<campaignnumlevels;i++){
7976                                                 levelvisible[i]=0;
7977                                                 levelhighlight[i]=0;
7978                                         }
7979
7980
7981                                         for(int i=0;i<campaignnumlevels;i++){
7982                                                 levelvisible[i]=0;
7983                                                 levelhighlight[i]=0;
7984                                         }
7985
7986                                         levelorder[0]=0;
7987                                         levelvisible[0]=1;
7988                                         for(int i=0;i<accountactive->getCampaignChoicesMade();i++){
7989                                                 levelorder[i+1]=campaignnextlevel[levelorder[i]][accountactive->getCampaignChoice(i)];
7990                                                 levelvisible[levelorder[i+1]]=1;
7991                                         }
7992                                         int whichlevelstart;
7993                                         whichlevelstart=accountactive->getCampaignChoicesMade()-1;
7994                                         if(whichlevelstart<0){
7995                                                 campaignchoicenum=1;
7996                                                 campaignchoicewhich[0]=0;
7997                                         }
7998                                         else
7999                                         {
8000                                                 campaignchoicenum=campaignnumnext[levelorder[whichlevelstart]];
8001                                                 for(int i=0;i<campaignchoicenum;i++){
8002                                                         campaignchoicewhich[i]=campaignnextlevel[levelorder[whichlevelstart]][i];
8003                                                         levelvisible[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
8004                                                         levelhighlight[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
8005                                                 }
8006                                         }
8007
8008                                         loading=2;
8009                                         loadtime=0;
8010                                         targetlevel=7;
8011                                         if(!firstload)LoadStuff();
8012                                         whichchoice=0;
8013                                         visibleloading=1;
8014                                         stillloading=1;
8015                                         Loadlevel(campaignmapname[campaignchoicewhich[0]]);
8016                                         campaign=1;
8017                                         mainmenu=0;
8018                                         gameon=1;
8019                                         pause_sound(stream_music3);
8020
8021                                         stealthloading=0;
8022                                 }
8023
8024             if(loading==3)
8025                 loading=0;
8026
8027         }
8028
8029         oldmusictype=musictype;
8030         }
8031
8032         facing=0;
8033         facing.z=-1;
8034
8035         facing=DoRotation(facing,-rotation2,0,0);
8036         facing=DoRotation(facing,0,0-rotation,0);
8037         viewerfacing=facing;
8038
8039         brotate=0;
8040         if(!cameramode){
8041                 if((animation[player[0].targetanimation].attack!=3&&animation[player[0].currentanimation].attack!=3)||player[0].skeleton.free)target=player[0].coords+player[0].currentoffset*(1-player[0].target)*player[0].scale+player[0].targetoffset*player[0].target*player[0].scale-player[0].facing*.05;
8042                 else target=player[0].oldcoords+player[0].currentoffset*(1-player[0].target)*player[0].scale+player[0].targetoffset*player[0].target*player[0].scale-player[0].facing*.05;
8043                 target.y+=.1;
8044                 if(player[0].skeleton.free){
8045                         for(int i=0;i<player[0].skeleton.num_joints;i++){
8046                                 if(player[0].skeleton.joints[i].position.y*player[0].scale+player[0].coords.y>target.y)
8047                                         target.y=player[0].skeleton.joints[i].position.y*player[0].scale+player[0].coords.y;
8048                         }
8049                         target.y+=.1;
8050                 }
8051                 if(player[0].skeleton.free!=2&&!autocam){
8052                         cameraspeed=20;
8053                         if(findLengthfast(&player[0].velocity)>400){
8054                                 cameraspeed=20+(findLength(&player[0].velocity)-20)*.96;
8055                         }
8056                         if(player[0].skeleton.free==0&&player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim)target.y+=1.4;
8057                         coltarget=target-cameraloc;
8058                         if(findLengthfast(&coltarget)<multiplier*multiplier*400)cameraloc=target;
8059                         else {
8060                                 Normalise(&coltarget);
8061                                 if(player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim&&player[0].currentanimation!=climbanim&&player[0].currentoffset.x==0)cameraloc=cameraloc+coltarget*multiplier*cameraspeed;
8062                                 else cameraloc=cameraloc+coltarget*multiplier*8;
8063                         }
8064                         if(editorenabled)cameraloc=target;
8065                         cameradist+=multiplier*5;
8066                         if(cameradist>2.3)cameradist=2.3;
8067                         viewer=cameraloc-facing*cameradist;
8068                         colviewer=viewer;
8069                         coltarget=cameraloc;
8070                         objects.SphereCheckPossible(&colviewer, findDistance(&colviewer,&coltarget));
8071                         if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8072                                 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8073                                         int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8074                                         colviewer=viewer;
8075                                         coltarget=cameraloc;
8076                                         if(objects.model[i].LineCheckPossible(&colviewer,&coltarget,&col,&objects.position[i],&objects.rotation[i])!=-1)viewer=col;
8077                                 }
8078             if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8079                 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8080                     int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8081                     colviewer=viewer;
8082                     if(objects.model[i].SphereCheck(&colviewer,.15,&col,&objects.position[i],&objects.rotation[i])!=-1){
8083                         viewer=colviewer;
8084                     }
8085                 }
8086             cameradist=findDistance(&viewer,&target);
8087             viewer.y=max((double)viewer.y,terrain.getHeight(viewer.x,viewer.z)+.6);
8088             if(cameraloc.y<terrain.getHeight(cameraloc.x,cameraloc.z)){
8089                 cameraloc.y=terrain.getHeight(cameraloc.x,cameraloc.z);
8090             }
8091                 }
8092                 if(player[0].skeleton.free!=2&&autocam){
8093                         cameraspeed=20;
8094                         if(findLengthfast(&player[0].velocity)>400){
8095                                 cameraspeed=20+(findLength(&player[0].velocity)-20)*.96;
8096                         }
8097                         if(player[0].skeleton.free==0&&player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim)target.y+=1.4;
8098                         cameradist+=multiplier*5;
8099                         if(cameradist>3.3)cameradist=3.3;
8100                         coltarget=target-cameraloc;
8101                         if(findLengthfast(&coltarget)<multiplier*multiplier*400)cameraloc=target;
8102                         else if(findLengthfast(&coltarget)>1)
8103                         {
8104                                 Normalise(&coltarget);
8105                                 if(player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim&&player[0].currentanimation!=climbanim&&player[0].currentoffset.x==0)cameraloc=cameraloc+coltarget*multiplier*cameraspeed;
8106                                 else cameraloc=cameraloc+coltarget*multiplier*8;
8107                         }
8108                         if(editorenabled)cameraloc=target;
8109                         viewer=cameraloc;
8110                         colviewer=viewer;
8111                         coltarget=cameraloc;
8112                         objects.SphereCheckPossible(&colviewer, findDistance(&colviewer,&coltarget));
8113                         if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8114                                 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8115                                         int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8116                                         colviewer=viewer;
8117                                         coltarget=cameraloc;
8118                                         if(objects.model[i].LineCheckPossible(&colviewer,&coltarget,&col,&objects.position[i],&objects.rotation[i])!=-1)viewer=col;
8119                                 }
8120             if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8121                 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8122                     int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8123                     colviewer=viewer;
8124                     if(objects.model[i].SphereCheck(&colviewer,.15,&col,&objects.position[i],&objects.rotation[i])!=-1){
8125                         viewer=colviewer;
8126                     }
8127                 }
8128             cameradist=findDistance(&viewer,&target);
8129             viewer.y=max((double)viewer.y,terrain.getHeight(viewer.x,viewer.z)+.6);
8130             if(cameraloc.y<terrain.getHeight(cameraloc.x,cameraloc.z)){
8131                 cameraloc.y=terrain.getHeight(cameraloc.x,cameraloc.z);
8132             }
8133                 }
8134                 if(camerashake>.8)camerashake=.8;
8135                 //if(woozy>10)woozy=10;
8136                 //woozy+=multiplier;
8137                 woozy+=multiplier;
8138                 if(player[0].dead)camerashake=0;
8139                 if(player[0].dead)woozy=0;
8140                 camerashake-=multiplier*2;
8141                 blackout-=multiplier*2;
8142                 //if(player[0].isCrouch())woozy-=multiplier*8;
8143                 if(camerashake<0)camerashake=0;
8144                 if(blackout<0)blackout=0;
8145                 //if(woozy<0)woozy=0;
8146                 if(camerashake){
8147                         viewer.x+=(float)(Random()%100)*.0005*camerashake;
8148                         viewer.y+=(float)(Random()%100)*.0005*camerashake;
8149                         viewer.z+=(float)(Random()%100)*.0005*camerashake;
8150                 }
8151         }
8152 }
8153