]> git.jsancho.org Git - lugaru.git/blob - Source/GameTick.cpp
player replaced by Person::players which is a vector of shared_ptr.
[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 <limits>
31 #include <ctime>
32 #include <dirent.h>
33 #include "Game.h"
34 #include "openal_wrapper.h"
35 #include "Settings.h"
36 #include "Input.h"
37 #include "Animation.h"
38 #include "Awards.h"
39 #include "Menu.h"
40
41 #include <algorithm>
42
43 using namespace std;
44 using namespace Game;
45
46 // Added more evilness needed for MSVC
47 #ifdef _MSC_VER
48 #define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
49 #define snprintf(buf, size, format, ...) _sprintf_p(buf, size, format)
50 #endif
51
52
53 extern float multiplier;
54 extern XYZ viewer;
55 extern int environment;
56 extern Terrain terrain;
57 extern float screenwidth, screenheight;
58 extern float gravity;
59 extern int detail;
60 extern float texdetail;
61 extern Objects objects;
62 extern int slomo;
63 extern float slomodelay;
64 extern bool floatjump;
65 extern float volume;
66 extern Light light;
67 extern float camerashake;
68 extern float woozy;
69 extern float blackout;
70 extern bool cellophane;
71 extern bool musictoggle;
72 extern int difficulty;
73 extern int bloodtoggle;
74 extern bool invertmouse;
75 extern float windvar;
76 extern float precipdelay;
77 extern XYZ viewerfacing;
78 extern bool ambientsound;
79 extern bool mousejump;
80 extern float viewdistance;
81 extern bool freeze;
82 extern bool keyboardfrozen;
83 extern bool loadingstuff;
84 extern XYZ windvector;
85 extern bool debugmode;
86 static int leveltheme;
87 extern int mainmenu;
88 extern int oldmainmenu;
89 extern bool visibleloading;
90 extern XYZ envsound[30];
91 extern float envsoundvol[30];
92 extern int numenvsounds;
93 extern float envsoundlife[30];
94 extern float usermousesensitivity;
95 extern bool ismotionblur;
96 extern bool showdamagebar; // (des)activate the damage bar
97 extern bool decals;
98 extern float tintr, tintg, tintb;
99 extern bool skyboxtexture;
100 extern float skyboxr;
101 extern float skyboxg;
102 extern float skyboxb;
103 extern float skyboxlightr;
104 extern float skyboxlightg;
105 extern float skyboxlightb;
106 extern float fadestart;
107 extern float slomospeed;
108 extern float slomofreq;
109 extern int tutoriallevel;
110 extern float smoketex;
111 extern float tutorialstagetime;
112 extern int tutorialstage;
113 extern float tutorialmaxtime;
114 extern float tutorialsuccess;
115 extern bool againbonus;
116 extern bool reversaltrain;
117 extern bool canattack;
118 extern bool cananger;
119 extern float damagedealt;
120 extern int maptype;
121 extern int editoractive;
122 extern int editorpathtype;
123 extern TGAImageRec texture;
124
125 extern float hostiletime;
126
127 extern bool gamestarted;
128
129 extern int numhotspots;
130 extern int killhotspot;
131 extern XYZ hotspot[40];
132 extern int hotspottype[40];
133 extern float hotspotsize[40];
134 extern char hotspottext[40][256];
135 extern int currenthotspot;
136
137 extern int hostile;
138
139 extern bool stillloading;
140 extern bool winfreeze;
141
142 extern bool campaign;
143
144
145
146 void Loadlevel(int which);
147 void Loadlevel(const char *name);
148
149
150
151 class CampaignLevel
152 {
153 private:
154     int width;
155     struct Position {
156         int x, y;
157     };
158 public:
159     std::string mapname;
160     std::string description;
161     int choosenext;
162     /*
163     0 = Immediately load next level at the end of this one.
164     1 = Go back to the world map.
165     2 = Don't bring up the Fiery loading screen. Maybe other things, I've not investigated.
166     */
167     //int numnext; // 0 on final level. As David said: he meant to add story branching, but he eventually hadn't.
168     std::vector<int> nextlevel;
169     Position location;
170     CampaignLevel() : width(10) {
171         choosenext = 1;
172         location.x = 0;
173         location.y = 0;
174     }
175     int getStartX() {
176         return 30 + 120 + location.x * 400 / 512;
177     }
178     int getStartY() {
179         return 30 + 30 + (512 - location.y) * 400 / 512;
180     }
181     int getEndX() {
182         return getStartX() + width;
183     }
184     int getEndY() {
185         return getStartY() + width;
186     }
187     XYZ getCenter() {
188         XYZ center;
189         center.x = getStartX() + width / 2;
190         center.y = getStartY() + width / 2;
191         return center;
192     }
193     int getWidth() {
194         return width;
195     }
196     istream& operator<< (istream& is) {
197         is.ignore(256, ':');
198         is.ignore(256, ':');
199         is.ignore(256, ' ');
200         is >> mapname;
201         is.ignore(256, ':');
202         is >> description;
203         for (unsigned pos = description.find('_'); pos != string::npos; pos = description.find('_', pos)) {
204             description.replace(pos, 1, 1, ' ');
205         }
206         is.ignore(256, ':');
207         is >> choosenext;
208         is.ignore(256, ':');
209         int numnext, next;
210         is >> numnext;
211         for (int j = 0; j < numnext; j++) {
212             is.ignore(256, ':');
213             is >> next;
214             nextlevel.push_back(next - 1);
215         }
216         is.ignore(256, ':');
217         is >> location.x;
218         is.ignore(256, ':');
219         is >> location.y;
220         return is;
221     }
222     friend istream& operator>> (istream& is, CampaignLevel& cl) {
223         return cl << is;
224     }
225 };
226
227 int indemo = 0;
228 bool won = false;
229 int entername = 0;
230 vector<CampaignLevel> campaignlevels;
231 int whichchoice = 0;
232 int actuallevel = 0;
233 bool winhotspot = false;
234 bool windialogue = false;
235 bool realthreat = 0;
236 XYZ cameraloc;
237 float cameradist = 0;
238 bool oldattackkey = 0;
239 int whichlevel = 0;
240 float musicvolume[4] = {};
241 float oldmusicvolume[4] = {};
242 int musicselected = 0;
243
244
245
246 static const char *rabbitskin[] = {
247     ":Data:Textures:Fur3.jpg",
248     ":Data:Textures:Fur.jpg",
249     ":Data:Textures:Fur2.jpg",
250     ":Data:Textures:Lynx.jpg",
251     ":Data:Textures:Otter.jpg",
252     ":Data:Textures:Opal.jpg",
253     ":Data:Textures:Sable.jpg",
254     ":Data:Textures:Chocolate.jpg",
255     ":Data:Textures:BW2.jpg",
256     ":Data:Textures:WB2.jpg"
257 };
258
259 static const char *wolfskin[] = {
260     ":Data:Textures:Wolf.jpg",
261     ":Data:Textures:Darkwolf.jpg",
262     ":Data:Textures:Snowwolf.jpg"
263 };
264
265 #define STATIC_ASSERT(x) extern int s_a_dummy[2 * (!!(x)) - 1];
266 STATIC_ASSERT (rabbittype == 0 && wolftype == 1)
267
268 static const char **creatureskin[] = {rabbitskin, wolfskin};
269
270 /* Return true if PFX is a prefix of STR (case-insensitive).  */
271 static bool stripfx(const char *str, const char *pfx)
272 {
273     return !strncasecmp(str, pfx, strlen(pfx));
274 }
275
276 static const char *cmd_names[] = {
277 #define DECLARE_COMMAND(cmd) #cmd,
278 #include "ConsoleCmds.h"
279 #undef  DECLARE_COMMAND
280 };
281
282 typedef void (*console_handler)(const char *args);
283
284 #define DECLARE_COMMAND(cmd) static void ch_##cmd(const char *args);
285 #include "ConsoleCmds.h"
286 #undef  DECLARE_COMMAND
287
288 static console_handler cmd_handlers[] = {
289 #define DECLARE_COMMAND(cmd) ch_##cmd,
290 #include "ConsoleCmds.h"
291 #undef  DECLARE_COMMAND
292 };
293
294
295
296 // utility functions
297
298 // TODO: this is slightly incorrect
299 inline float roughDirection(XYZ vec)
300 {
301     Normalise(&vec);
302     float angle = -asin(-vec.x) * 180 / M_PI;
303     if (vec.z < 0)
304         angle = 180 - angle;
305     return angle;
306 }
307 inline float roughDirectionTo(XYZ start, XYZ end)
308 {
309     return roughDirection(end - start);
310 }
311 inline float pitchOf(XYZ vec)
312 {
313     Normalise(&vec);
314     return -asin(vec.y) * 180 / M_PI;
315 }
316 inline float pitchTo(XYZ start, XYZ end)
317 {
318     return pitchOf(end - start);
319 }
320 inline float sq(float n)
321 {
322     return n * n;
323 }
324 inline float stepTowardf(float from, float to, float by)
325 {
326     if (fabs(from - to) < by)
327         return to;
328     else if (from > to)
329         return from - by;
330     else
331         return from + by;
332 }
333
334 void playdialogueboxsound()
335 {
336     XYZ temppos;
337     temppos = Person::players[participantfocus[whichdialogue][indialogue]]->coords;
338     temppos = temppos - viewer;
339     Normalise(&temppos);
340     temppos += viewer;
341
342     int sound = -1;
343     switch (dialogueboxsound[whichdialogue][indialogue]) {
344     case -6:
345         sound = alarmsound;
346         break;
347     case -4:
348         sound = consolefailsound;
349         break;
350     case -3:
351         sound = consolesuccesssound;
352         break;
353     case -2:
354         sound = firestartsound;
355         break;
356     case -1:
357         sound = fireendsound;
358         break;
359     case 1:
360         sound = rabbitchitter;
361         break;
362     case 2:
363         sound = rabbitchitter2;
364         break;
365     case 3:
366         sound = rabbitpainsound;
367         break;
368     case 4:
369         sound = rabbitpain1sound;
370         break;
371     case 5:
372         sound = rabbitattacksound;
373         break;
374     case 6:
375         sound = rabbitattack2sound;
376         break;
377     case 7:
378         sound = rabbitattack3sound;
379         break;
380     case 8:
381         sound = rabbitattack4sound;
382         break;
383     case 9:
384         sound = growlsound;
385         break;
386     case 10:
387         sound = growl2sound;
388         break;
389     case 11:
390         sound = snarlsound;
391         break;
392     case 12:
393         sound = snarl2sound;
394         break;
395     case 13:
396         sound = barksound;
397         break;
398     case 14:
399         sound = bark2sound;
400         break;
401     case 15:
402         sound = bark3sound;
403         break;
404     case 16:
405         sound = barkgrowlsound;
406         break;
407     default:
408         break;
409     }
410     if (sound != -1)
411         emit_sound_at(sound, temppos);
412 }
413
414 // ================================================================
415
416 bool AddClothes(const char *fileName, GLubyte *array)
417 {
418     LOGFUNC;
419     //Load Image
420     unsigned char fileNamep[256];
421     CopyCStringToPascal(fileName, fileNamep);
422     bool opened;
423     opened = upload_image( fileNamep , 1);
424
425     float alphanum;
426     //Is it valid?
427     if (opened) {
428         if (tintr > 1) tintr = 1;
429         if (tintg > 1) tintg = 1;
430         if (tintb > 1) tintb = 1;
431
432         if (tintr < 0) tintr = 0;
433         if (tintg < 0) tintg = 0;
434         if (tintb < 0) tintb = 0;
435
436         int bytesPerPixel = texture.bpp / 8;
437
438         int tempnum = 0;
439         alphanum = 255;
440         for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
441             if (bytesPerPixel == 3)
442                 alphanum = 255;
443             else if ((i + 1) % 4 == 0)
444                 alphanum = texture.data[i];
445             //alphanum/=2;
446             if ((i + 1) % 4 || bytesPerPixel == 3) {
447                 if ((i % 4) == 0)
448                     texture.data[i] *= tintr;
449                 if ((i % 4) == 1)
450                     texture.data[i] *= tintg;
451                 if ((i % 4) == 2)
452                     texture.data[i] *= tintb;
453                 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
454                 tempnum++;
455             }
456         }
457     } else
458         return 0;
459     return 1;
460 }
461
462
463
464 static void ch_quit(const char *args)
465 {
466     tryquit = 1;
467 }
468
469 static void ch_map(const char *args)
470 {
471     Loadlevel(args);
472     whichlevel = -2;
473     campaign = 0;
474 }
475
476 static void ch_save(const char *args)
477 {
478     char buf[64];
479     snprintf(buf, 63, ":Data:Maps:%s", args);
480
481     int mapvers = 12;
482
483     FILE *tfile;
484     tfile = fopen( ConvertFileName(buf), "wb" );
485     fpackf(tfile, "Bi", mapvers);
486     fpackf(tfile, "Bi", maptype);
487     fpackf(tfile, "Bi", hostile);
488     fpackf(tfile, "Bf Bf", viewdistance, fadestart);
489     fpackf(tfile, "Bb Bf Bf Bf", skyboxtexture, skyboxr, skyboxg, skyboxb);
490     fpackf(tfile, "Bf Bf Bf", skyboxlightr, skyboxlightg, skyboxlightb);
491     fpackf(tfile, "Bf Bf Bf Bf Bf Bi", Person::players[0]->coords.x, Person::players[0]->coords.y, Person::players[0]->coords.z,
492            Person::players[0]->yaw, Person::players[0]->targetyaw, Person::players[0]->num_weapons);
493     if (Person::players[0]->num_weapons > 0 && Person::players[0]->num_weapons < 5)
494         for (int j = 0; j < Person::players[0]->num_weapons; j++)
495             fpackf(tfile, "Bi", weapons[Person::players[0]->weaponids[j]].getType());
496
497     fpackf(tfile, "Bf Bf Bf", Person::players[0]->armorhead, Person::players[0]->armorhigh, Person::players[0]->armorlow);
498     fpackf(tfile, "Bf Bf Bf", Person::players[0]->protectionhead, Person::players[0]->protectionhigh, Person::players[0]->protectionlow);
499     fpackf(tfile, "Bf Bf Bf", Person::players[0]->metalhead, Person::players[0]->metalhigh, Person::players[0]->metallow);
500     fpackf(tfile, "Bf Bf", Person::players[0]->power, Person::players[0]->speedmult);
501
502     fpackf(tfile, "Bi", Person::players[0]->numclothes);
503
504     fpackf(tfile, "Bi Bi", Person::players[0]->whichskin, Person::players[0]->creature);
505
506     fpackf(tfile, "Bi", numdialogues);
507
508     for (int k = 0; k < numdialogues; k++) {
509         fpackf(tfile, "Bi", numdialogueboxes[k]);
510         fpackf(tfile, "Bi", dialoguetype[k]);
511         for (int l = 0; l < 10; l++) {
512             fpackf(tfile, "Bf Bf Bf", participantlocation[k][l].x, participantlocation[k][l].y, participantlocation[k][l].z);
513             fpackf(tfile, "Bf", participantyaw[k][l]);
514         }
515         for (int l = 0; l < numdialogueboxes[k]; l++) {
516             fpackf(tfile, "Bi", dialogueboxlocation[k][l]);
517             fpackf(tfile, "Bf", dialogueboxcolor[k][l][0]);
518             fpackf(tfile, "Bf", dialogueboxcolor[k][l][1]);
519             fpackf(tfile, "Bf", dialogueboxcolor[k][l][2]);
520             fpackf(tfile, "Bi", dialogueboxsound[k][l]);
521
522             int templength = strlen(dialoguetext[k][l]);
523             fpackf(tfile, "Bi", (templength));
524             for (int m = 0; m < templength; m++) {
525                 fpackf(tfile, "Bb", dialoguetext[k][l][m]);
526                 if (dialoguetext[k][l][m] == '\0')
527                     break;
528             }
529
530             templength = strlen(dialoguename[k][l]);
531             fpackf(tfile, "Bi", templength);
532             for (int m = 0; m < templength; m++) {
533                 fpackf(tfile, "Bb", dialoguename[k][l][m]);
534                 if (dialoguename[k][l][m] == '\0')
535                     break;
536             }
537
538             fpackf(tfile, "Bf Bf Bf", dialoguecamera[k][l].x, dialoguecamera[k][l].y, dialoguecamera[k][l].z);
539             fpackf(tfile, "Bi", participantfocus[k][l]);
540             fpackf(tfile, "Bi", participantaction[k][l]);
541
542             for (int m = 0; m < 10; m++)
543                 fpackf(tfile, "Bf Bf Bf", participantfacing[k][l][m].x, participantfacing[k][l][m].y, participantfacing[k][l][m].z);
544
545             fpackf(tfile, "Bf Bf", dialoguecamerayaw[k][l], dialoguecamerapitch[k][l]);
546         }
547     }
548
549     for (int k = 0; k < Person::players[0]->numclothes; k++) {
550         int templength = strlen(Person::players[0]->clothes[k]);
551         fpackf(tfile, "Bi", templength);
552         for (int l = 0; l < templength; l++)
553             fpackf(tfile, "Bb", Person::players[0]->clothes[k][l]);
554         fpackf(tfile, "Bf Bf Bf", Person::players[0]->clothestintr[k], Person::players[0]->clothestintg[k], Person::players[0]->clothestintb[k]);
555     }
556
557     fpackf(tfile, "Bi", environment);
558
559     fpackf(tfile, "Bi", objects.numobjects);
560
561     for (int k = 0; k < objects.numobjects; k++)
562         fpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", objects.type[k], objects.yaw[k], objects.pitch[k],
563                objects.position[k].x, objects.position[k].y, objects.position[k].z, objects.scale[k]);
564
565     fpackf(tfile, "Bi", numhotspots);
566     for (int i = 0; i < numhotspots; i++) {
567         fpackf(tfile, "Bi Bf Bf Bf Bf", hotspottype[i], hotspotsize[i], hotspot[i].x, hotspot[i].y, hotspot[i].z);
568         int templength = strlen(hotspottext[i]);
569         fpackf(tfile, "Bi", templength);
570         for (int l = 0; l < templength; l++)
571             fpackf(tfile, "Bb", hotspottext[i][l]);
572     }
573
574     fpackf(tfile, "Bi", numplayers);
575     if (numplayers < maxplayers)
576         for (int j = 1; j < numplayers; j++) {
577             fpackf(tfile, "Bi Bi Bf Bf Bf Bi Bi Bf Bb Bf", Person::players[j]->whichskin, Person::players[j]->creature,
578                    Person::players[j]->coords.x, Person::players[j]->coords.y, Person::players[j]->coords.z,
579                    Person::players[j]->num_weapons, Person::players[j]->howactive, Person::players[j]->scale, Person::players[j]->immobile, Person::players[j]->yaw);
580             if (Person::players[j]->num_weapons < 5)
581                 for (int k = 0; k < Person::players[j]->num_weapons; k++)
582                     fpackf(tfile, "Bi", weapons[Person::players[j]->weaponids[k]].getType());
583             if (Person::players[j]->numwaypoints < 30) {
584                 fpackf(tfile, "Bi", Person::players[j]->numwaypoints);
585                 for (int k = 0; k < Person::players[j]->numwaypoints; k++) {
586                     fpackf(tfile, "Bf", Person::players[j]->waypoints[k].x);
587                     fpackf(tfile, "Bf", Person::players[j]->waypoints[k].y);
588                     fpackf(tfile, "Bf", Person::players[j]->waypoints[k].z);
589                     fpackf(tfile, "Bi", Person::players[j]->waypointtype[k]);
590                 }
591                 fpackf(tfile, "Bi", Person::players[j]->waypoint);
592             } else {
593                 Person::players[j]->numwaypoints = 0;
594                 Person::players[j]->waypoint = 0;
595                 fpackf(tfile, "Bi Bi Bi", Person::players[j]->numwaypoints, Person::players[j]->waypoint, Person::players[j]->waypoint);
596             }
597
598             fpackf(tfile, "Bf Bf Bf", Person::players[j]->armorhead, Person::players[j]->armorhigh, Person::players[j]->armorlow);
599             fpackf(tfile, "Bf Bf Bf", Person::players[j]->protectionhead, Person::players[j]->protectionhigh, Person::players[j]->protectionlow);
600             fpackf(tfile, "Bf Bf Bf", Person::players[j]->metalhead, Person::players[j]->metalhigh, Person::players[j]->metallow);
601             fpackf(tfile, "Bf Bf", Person::players[j]->power, Person::players[j]->speedmult);
602
603             float headprop, bodyprop, armprop, legprop;
604             if (Person::players[j]->creature == wolftype) {
605                 headprop = Person::players[j]->proportionhead.x / 1.1;
606                 bodyprop = Person::players[j]->proportionbody.x / 1.1;
607                 armprop = Person::players[j]->proportionarms.x / 1.1;
608                 legprop = Person::players[j]->proportionlegs.x / 1.1;
609             } else if (Person::players[j]->creature == rabbittype) {
610                 headprop = Person::players[j]->proportionhead.x / 1.2;
611                 bodyprop = Person::players[j]->proportionbody.x / 1.05;
612                 armprop = Person::players[j]->proportionarms.x / 1.00;
613                 legprop = Person::players[j]->proportionlegs.x / 1.1;
614             }
615
616             fpackf(tfile, "Bf Bf Bf Bf", headprop, bodyprop, armprop, legprop);
617
618             fpackf(tfile, "Bi", Person::players[j]->numclothes);
619             if (Person::players[j]->numclothes)
620                 for (int k = 0; k < Person::players[j]->numclothes; k++) {
621                     int templength;
622                     templength = strlen(Person::players[j]->clothes[k]);
623                     fpackf(tfile, "Bi", templength);
624                     for (int l = 0; l < templength; l++)
625                         fpackf(tfile, "Bb", Person::players[j]->clothes[k][l]);
626                     fpackf(tfile, "Bf Bf Bf", Person::players[j]->clothestintr[k], Person::players[j]->clothestintg[k], Person::players[j]->clothestintb[k]);
627                 }
628         }
629
630     fpackf(tfile, "Bi", numpathpoints);
631     for (int j = 0; j < numpathpoints; j++) {
632         fpackf(tfile, "Bf Bf Bf Bi", pathpoint[j].x, pathpoint[j].y, pathpoint[j].z, numpathpointconnect[j]);
633         for (int k = 0; k < numpathpointconnect[j]; k++)
634             fpackf(tfile, "Bi", pathpointconnect[j][k]);
635     }
636
637     fpackf(tfile, "Bf Bf Bf Bf", mapcenter.x, mapcenter.y, mapcenter.z, mapradius);
638
639     fclose(tfile);
640 }
641
642 static void ch_cellar(const char *args)
643 {
644     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:Furdarko.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
645 }
646
647 static void ch_tint(const char *args)
648 {
649     sscanf(args, "%f%f%f", &tintr, &tintg, &tintb);
650 }
651
652 static void ch_tintr(const char *args)
653 {
654     tintr = atof(args);
655 }
656
657 static void ch_tintg(const char *args)
658 {
659     tintg = atof(args);
660 }
661
662 static void ch_tintb(const char *args)
663 {
664     tintb = atof(args);
665 }
666
667 static void ch_speed(const char *args)
668 {
669     Person::players[0]->speedmult = atof(args);
670 }
671
672 static void ch_strength(const char *args)
673 {
674     Person::players[0]->power = atof(args);
675 }
676
677 static void ch_power(const char *args)
678 {
679     Person::players[0]->power = atof(args);
680 }
681
682 static void ch_size(const char *args)
683 {
684     Person::players[0]->scale = atof(args) * .2;
685 }
686
687 static int findClosestPlayer()
688 {
689     int closest = -1;
690     float closestdist = std::numeric_limits<float>::max();
691
692     for (int i = 1; i < numplayers; i++) {
693         float distance = distsq(&Person::players[i]->coords, &Person::players[0]->coords);
694         if (distance < closestdist) {
695             closestdist = distance;
696             closest = i;
697         }
698     }
699     return closest;
700 }
701
702 static int findClosestObject()
703 {
704     int closest = -1;
705     float closestdist = std::numeric_limits<float>::max();
706
707     for (int i = 0; i < objects.numobjects; i++) {
708         float distance = distsq(&objects.position[i], &Person::players[0]->coords);
709         if (distance < closestdist) {
710             closestdist = distance;
711             closest = i;
712         }
713     }
714     return closest;
715 }
716
717 static void ch_sizenear(const char *args)
718 {
719     int closest = findClosestPlayer();
720     if (closest >= 0)
721         Person::players[closest]->scale = atof(args) * .2;
722 }
723
724 static void set_proportion(int pnum, const char *args)
725 {
726     float headprop, bodyprop, armprop, legprop;
727
728     sscanf(args, "%f%f%f%f", &headprop, &bodyprop, &armprop, &legprop);
729
730     if (Person::players[pnum]->creature == wolftype) {
731         Person::players[pnum]->proportionhead = 1.1 * headprop;
732         Person::players[pnum]->proportionbody = 1.1 * bodyprop;
733         Person::players[pnum]->proportionarms = 1.1 * armprop;
734         Person::players[pnum]->proportionlegs = 1.1 * legprop;
735     } else if (Person::players[pnum]->creature == rabbittype) {
736         Person::players[pnum]->proportionhead = 1.2 * headprop;
737         Person::players[pnum]->proportionbody = 1.05 * bodyprop;
738         Person::players[pnum]->proportionarms = 1.00 * armprop;
739         Person::players[pnum]->proportionlegs = 1.1 * legprop;
740         Person::players[pnum]->proportionlegs.y = 1.05 * legprop;
741     }
742 }
743
744 static void ch_proportion(const char *args)
745 {
746     set_proportion(0, args);
747 }
748
749 static void ch_proportionnear(const char *args)
750 {
751     int closest = findClosestPlayer();
752     if (closest >= 0)
753         set_proportion(closest, args);
754 }
755
756 static void set_protection(int pnum, const char *args)
757 {
758     float head, high, low;
759     sscanf(args, "%f%f%f", &head, &high, &low);
760
761     Person::players[pnum]->protectionhead = head;
762     Person::players[pnum]->protectionhigh = high;
763     Person::players[pnum]->protectionlow  = low;
764 }
765
766 static void ch_protection(const char *args)
767 {
768     set_protection(0, args);
769 }
770
771 static void ch_protectionnear(const char *args)
772 {
773     int closest = findClosestPlayer();
774     if (closest >= 0)
775         set_protection(closest, args);
776 }
777
778 static void set_armor(int pnum, const char *args)
779 {
780     float head, high, low;
781     sscanf(args, "%f%f%f", &head, &high, &low);
782
783     Person::players[pnum]->armorhead = head;
784     Person::players[pnum]->armorhigh = high;
785     Person::players[pnum]->armorlow  = low;
786 }
787
788 static void ch_armor(const char *args)
789 {
790     set_armor(0, args);
791 }
792
793 static void ch_armornear(const char *args)
794 {
795     int closest = findClosestPlayer();
796     if (closest >= 0)
797         set_armor(closest, args);
798 }
799
800 static void ch_protectionreset(const char *args)
801 {
802     set_protection(0, "1 1 1");
803     set_armor(0, "1 1 1");
804 }
805
806 static void set_metal(int pnum, const char *args)
807 {
808     float head, high, low;
809     sscanf(args, "%f%f%f", &head, &high, &low);
810
811     Person::players[pnum]->metalhead = head;
812     Person::players[pnum]->metalhigh = high;
813     Person::players[pnum]->metallow  = low;
814 }
815
816 static void ch_metal(const char *args)
817 {
818     set_metal(0, args);
819 }
820
821 static void set_noclothes(int pnum, const char *args)
822 {
823     Person::players[pnum]->numclothes = 0;
824     Person::players[pnum]->skeleton.drawmodel.textureptr.load(
825         creatureskin[Person::players[pnum]->creature][Person::players[pnum]->whichskin], 1,
826         &Person::players[pnum]->skeleton.skinText[0], &Person::players[pnum]->skeleton.skinsize);
827 }
828
829 static void ch_noclothes(const char *args)
830 {
831     set_noclothes(0, args);
832 }
833
834 static void ch_noclothesnear(const char *args)
835 {
836     int closest = findClosestPlayer();
837     if (closest >= 0)
838         set_noclothes(closest, args);
839 }
840
841
842 static void set_clothes(int pnum, const char *args)
843 {
844     char buf[64];
845     snprintf(buf, 63, ":Data:Textures:%s.png", args);
846
847     if (!AddClothes(buf, &Person::players[pnum]->skeleton.skinText[pnum]))
848         return;
849
850     Person::players[pnum]->DoMipmaps();
851     strcpy(Person::players[pnum]->clothes[Person::players[pnum]->numclothes], buf);
852     Person::players[pnum]->clothestintr[Person::players[pnum]->numclothes] = tintr;
853     Person::players[pnum]->clothestintg[Person::players[pnum]->numclothes] = tintg;
854     Person::players[pnum]->clothestintb[Person::players[pnum]->numclothes] = tintb;
855     Person::players[pnum]->numclothes++;
856 }
857
858 static void ch_clothes(const char *args)
859 {
860     set_clothes(0, args);
861 }
862
863 static void ch_clothesnear(const char *args)
864 {
865     int closest = findClosestPlayer();
866     if (closest >= 0)
867         set_clothes(closest, args);
868 }
869
870 static void ch_belt(const char *args)
871 {
872     Person::players[0]->skeleton.clothes = !Person::players[0]->skeleton.clothes;
873 }
874
875
876 static void ch_cellophane(const char *args)
877 {
878     cellophane = !cellophane;
879     float mul = cellophane ? 0 : 1;
880
881     for (int i = 0; i < numplayers; i++) {
882         Person::players[i]->proportionhead.z = Person::players[i]->proportionhead.x * mul;
883         Person::players[i]->proportionbody.z = Person::players[i]->proportionbody.x * mul;
884         Person::players[i]->proportionarms.z = Person::players[i]->proportionarms.x * mul;
885         Person::players[i]->proportionlegs.z = Person::players[i]->proportionlegs.x * mul;
886     }
887 }
888
889 static void ch_funnybunny(const char *args)
890 {
891     Person::players[0]->skeleton.id = 0;
892     Person::players[0]->skeleton.Load(":Data:Skeleton:Basic Figure", ":Data:Skeleton:Basic Figurelow",
893                             ":Data:Skeleton:Rabbitbelt", ":Data:Models:Body.solid",
894                             ":Data:Models:Body2.solid", ":Data:Models:Body3.solid",
895                             ":Data:Models:Body4.solid", ":Data:Models:Body5.solid",
896                             ":Data:Models:Body6.solid", ":Data:Models:Body7.solid",
897                             ":Data:Models:Bodylow.solid", ":Data:Models:Belt.solid", 1);
898     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:fur3.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
899     Person::players[0]->creature = rabbittype;
900     Person::players[0]->scale = .2;
901     Person::players[0]->headless = 0;
902     Person::players[0]->damagetolerance = 200;
903     set_proportion(0, "1 1 1 1");
904 }
905
906 static void ch_wolfie(const char *args)
907 {
908     Person::players[0]->skeleton.id = 0;
909     Person::players[0]->skeleton.Load(":Data:Skeleton:Basic Figure Wolf", ":Data:Skeleton:Basic Figure Wolf Low",
910                             ":Data:Skeleton:Rabbitbelt", ":Data:Models:Wolf.solid",
911                             ":Data:Models:Wolf2.solid", ":Data:Models:Wolf3.solid",
912                             ":Data:Models:Wolf4.solid", ":Data:Models:Wolf5.solid",
913                             ":Data:Models:Wolf6.solid", ":Data:Models:Wolf7.solid",
914                             ":Data:Models:Wolflow.solid", ":Data:Models:Belt.solid", 0);
915     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
916     Person::players[0]->creature = wolftype;
917     Person::players[0]->damagetolerance = 300;
918     set_proportion(0, "1 1 1 1");
919 }
920
921 static void ch_wolfieisgod(const char *args)
922 {
923     ch_wolfie(args);
924 }
925
926 static void ch_wolf(const char *args)
927 {
928     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
929 }
930
931 static void ch_snowwolf(const char *args)
932 {
933     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:SnowWolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
934 }
935
936 static void ch_darkwolf(const char *args)
937 {
938     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:DarkWolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
939 }
940
941 static void ch_lizardwolf(const char *args)
942 {
943     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:Lizardwolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
944 }
945
946 static void ch_white(const char *args)
947 {
948     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:fur.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
949 }
950
951 static void ch_brown(const char *args)
952 {
953     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:fur3.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
954 }
955
956 static void ch_black(const char *args)
957 {
958     Person::players[0]->skeleton.drawmodel.textureptr.load(":Data:Textures:fur2.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
959 }
960
961 static void ch_sizemin(const char *args)
962 {
963     for (int i = 1; i < numplayers; i++)
964         if (Person::players[i]->scale < 0.8 * 0.2)
965             Person::players[i]->scale = 0.8 * 0.2;
966 }
967
968 static void ch_tutorial(const char *args)
969 {
970     tutoriallevel = atoi(args);
971 }
972
973 static void ch_hostile(const char *args)
974 {
975     hostile = atoi(args);
976 }
977
978 static void ch_indemo(const char *args)
979 {
980     indemo = 1;
981     hotspot[numhotspots] = Person::players[0]->coords;
982     hotspotsize[numhotspots] = 0;
983     hotspottype[numhotspots] = -111;
984     strcpy(hotspottext[numhotspots], "mapname");
985     numhotspots++;
986 }
987
988 static void ch_notindemo(const char *args)
989 {
990     indemo = 0;
991     numhotspots--;
992 }
993
994 static void ch_type(const char *args)
995 {
996     int n = sizeof(editortypenames) / sizeof(editortypenames[0]);
997     for (int i = 0; i < n; i++)
998         if (stripfx(args, editortypenames[i])) {
999             editoractive = i;
1000             break;
1001         }
1002 }
1003
1004 static void ch_path(const char *args)
1005 {
1006     int n = sizeof(pathtypenames) / sizeof(pathtypenames[0]);
1007     for (int i = 0; i < n; i++)
1008         if (stripfx(args, pathtypenames[i])) {
1009             editorpathtype = i;
1010             break;
1011         }
1012 }
1013
1014 static void ch_hs(const char *args)
1015 {
1016     hotspot[numhotspots] = Person::players[0]->coords;
1017
1018     float size;
1019     int type, shift;
1020     sscanf(args, "%f%d %n", &size, &type, &shift);
1021
1022     hotspotsize[numhotspots] = size;
1023     hotspottype[numhotspots] = type;
1024
1025     strcpy(hotspottext[numhotspots], args + shift);
1026     strcat(hotspottext[numhotspots], "\n");
1027
1028     numhotspots++;
1029 }
1030
1031 static void ch_dialogue(const char *args)
1032 {
1033     int dlg;
1034     char buf1[32], buf2[64];
1035
1036     sscanf(args, "%d %31s", &dlg, buf1);
1037     snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
1038
1039     dialoguetype[numdialogues] = dlg;
1040
1041     memset(dialoguetext[numdialogues], 0, sizeof(dialoguetext[numdialogues]));
1042     memset(dialoguename[numdialogues], 0, sizeof(dialoguename[numdialogues]));
1043
1044     ifstream ipstream(ConvertFileName(buf2));
1045     ipstream.ignore(256, ':');
1046     ipstream >> numdialogueboxes[numdialogues];
1047     for (int i = 0; i < numdialogueboxes[numdialogues]; i++) {
1048         ipstream.ignore(256, ':');
1049         ipstream.ignore(256, ':');
1050         ipstream.ignore(256, ' ');
1051         ipstream >> dialogueboxlocation[numdialogues][i];
1052         ipstream.ignore(256, ':');
1053         ipstream >> dialogueboxcolor[numdialogues][i][0];
1054         ipstream >> dialogueboxcolor[numdialogues][i][1];
1055         ipstream >> dialogueboxcolor[numdialogues][i][2];
1056         ipstream.ignore(256, ':');
1057         ipstream.getline(dialoguename[numdialogues][i], 64);
1058         ipstream.ignore(256, ':');
1059         ipstream.ignore(256, ' ');
1060         ipstream.getline(dialoguetext[numdialogues][i], 128);
1061         for (int j = 0; j < 128; j++) {
1062             if (dialoguetext[numdialogues][i][j] == '\\')
1063                 dialoguetext[numdialogues][i][j] = '\n';
1064         }
1065         ipstream.ignore(256, ':');
1066         ipstream >> dialogueboxsound[numdialogues][i];
1067     }
1068
1069     for (int i = 0; i < numdialogueboxes[numdialogues]; i++) {
1070         for (int j = 0; j < numplayers; j++) {
1071             participantfacing[numdialogues][i][j] = Person::players[j]->facing;
1072         }
1073     }
1074     ipstream.close();
1075
1076     directing = 1;
1077     indialogue = 0;
1078     whichdialogue = numdialogues;
1079
1080     numdialogues++;
1081 }
1082
1083 static void ch_fixdialogue(const char *args)
1084 {
1085     char buf1[32], buf2[64];
1086     int whichdi;
1087
1088     sscanf(args, "%d %31s", &whichdi, buf1);
1089     snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
1090
1091     memset(dialoguetext[whichdi], 0, sizeof(dialoguetext[whichdi]));
1092     memset(dialoguename[whichdi], 0, sizeof(dialoguename[whichdi]));
1093
1094     ifstream ipstream(ConvertFileName(buf2));
1095     ipstream.ignore(256, ':');
1096     ipstream >> numdialogueboxes[whichdi];
1097     for (int i = 0; i < numdialogueboxes[whichdi]; i++) {
1098         ipstream.ignore(256, ':');
1099         ipstream.ignore(256, ':');
1100         ipstream.ignore(256, ' ');
1101         ipstream >> dialogueboxlocation[whichdi][i];
1102         ipstream.ignore(256, ':');
1103         ipstream >> dialogueboxcolor[whichdi][i][0];
1104         ipstream >> dialogueboxcolor[whichdi][i][1];
1105         ipstream >> dialogueboxcolor[whichdi][i][2];
1106         ipstream.ignore(256, ':');
1107         ipstream.getline(dialoguename[whichdi][i], 64);
1108         ipstream.ignore(256, ':');
1109         ipstream.ignore(256, ' ');
1110         ipstream.getline(dialoguetext[whichdi][i], 128);
1111         for (int j = 0; j < 128; j++) {
1112             if (dialoguetext[whichdi][i][j] == '\\')
1113                 dialoguetext[whichdi][i][j] = '\n';
1114         }
1115         ipstream.ignore(256, ':');
1116         ipstream >> dialogueboxsound[whichdi][i];
1117     }
1118
1119     ipstream.close();
1120 }
1121
1122 static void ch_fixtype(const char *args)
1123 {
1124     int dlg;
1125     sscanf(args, "%d", &dlg);
1126     dialoguetype[0] = dlg;
1127 }
1128
1129 static void ch_fixrotation(const char *args)
1130 {
1131     participantyaw[whichdialogue][participantfocus[whichdialogue][indialogue]] = Person::players[participantfocus[whichdialogue][indialogue]]->yaw;
1132 }
1133
1134 static void ch_ddialogue(const char *args)
1135 {
1136     if (numdialogues)
1137         numdialogues--;
1138 }
1139
1140 static void ch_dhs(const char *args)
1141 {
1142     if (numhotspots)
1143         numhotspots--;
1144 }
1145
1146 static void ch_immobile(const char *args)
1147 {
1148     Person::players[0]->immobile = 1;
1149 }
1150
1151 static void ch_allimmobile(const char *args)
1152 {
1153     for (int i = 1; i < numplayers; i++)
1154         Person::players[i]->immobile = 1;
1155 }
1156
1157 static void ch_mobile(const char *args)
1158 {
1159     Person::players[0]->immobile = 0;
1160 }
1161
1162 static void ch_default(const char *args)
1163 {
1164     Person::players[0]->armorhead = 1;
1165     Person::players[0]->armorhigh = 1;
1166     Person::players[0]->armorlow = 1;
1167     Person::players[0]->protectionhead = 1;
1168     Person::players[0]->protectionhigh = 1;
1169     Person::players[0]->protectionlow = 1;
1170     Person::players[0]->metalhead = 1;
1171     Person::players[0]->metalhigh = 1;
1172     Person::players[0]->metallow = 1;
1173     Person::players[0]->power = 1;
1174     Person::players[0]->speedmult = 1;
1175     Person::players[0]->scale = 1;
1176
1177     if (Person::players[0]->creature == wolftype) {
1178         Person::players[0]->proportionhead = 1.1;
1179         Person::players[0]->proportionbody = 1.1;
1180         Person::players[0]->proportionarms = 1.1;
1181         Person::players[0]->proportionlegs = 1.1;
1182     } else if (Person::players[0]->creature == rabbittype) {
1183         Person::players[0]->proportionhead = 1.2;
1184         Person::players[0]->proportionbody = 1.05;
1185         Person::players[0]->proportionarms = 1.00;
1186         Person::players[0]->proportionlegs = 1.1;
1187         Person::players[0]->proportionlegs.y = 1.05;
1188     }
1189
1190     Person::players[0]->numclothes = 0;
1191     Person::players[0]->skeleton.drawmodel.textureptr.load(
1192         creatureskin[Person::players[0]->creature][Person::players[0]->whichskin], 1,
1193         &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
1194
1195     editoractive = typeactive;
1196     Person::players[0]->immobile = 0;
1197 }
1198
1199 static void ch_play(const char *args)
1200 {
1201     int dlg;
1202     sscanf(args, "%d", &dlg);
1203     whichdialogue = dlg;
1204
1205     if (whichdialogue >= numdialogues)
1206         return;
1207
1208     for (int i = 0; i < numdialogueboxes[whichdialogue]; i++) {
1209         Person::players[participantfocus[whichdialogue][i]]->coords = participantlocation[whichdialogue][participantfocus[whichdialogue][i]];
1210         Person::players[participantfocus[whichdialogue][i]]->yaw = participantyaw[whichdialogue][participantfocus[whichdialogue][i]];
1211         Person::players[participantfocus[whichdialogue][i]]->targetyaw = participantyaw[whichdialogue][participantfocus[whichdialogue][i]];
1212         Person::players[participantfocus[whichdialogue][i]]->velocity = 0;
1213         Person::players[participantfocus[whichdialogue][i]]->animTarget = Person::players[participantfocus[whichdialogue][i]]->getIdle();
1214         Person::players[participantfocus[whichdialogue][i]]->frameTarget = 0;
1215     }
1216
1217     directing = 0;
1218     indialogue = 0;
1219
1220     playdialogueboxsound();
1221 }
1222
1223 static void ch_mapkilleveryone(const char *args)
1224 {
1225     maptype = mapkilleveryone;
1226 }
1227
1228 static void ch_mapkillmost(const char *args)
1229 {
1230     maptype = mapkillmost;
1231 }
1232
1233 static void ch_mapkillsomeone(const char *args)
1234 {
1235     maptype = mapkillsomeone;
1236 }
1237
1238 static void ch_mapgosomewhere(const char *args)
1239 {
1240     maptype = mapgosomewhere;
1241 }
1242
1243 static void ch_viewdistance(const char *args)
1244 {
1245     viewdistance = atof(args) * 100;
1246 }
1247
1248 static void ch_fadestart(const char *args)
1249 {
1250     fadestart = atof(args);
1251 }
1252
1253 static void ch_slomo(const char *args)
1254 {
1255     slomospeed = atof(args);
1256     slomo = !slomo;
1257     slomodelay = 1000;
1258 }
1259
1260 static void ch_slofreq(const char *args)
1261 {
1262     slomofreq = atof(args);
1263 }
1264
1265 static void ch_skytint(const char *args)
1266 {
1267     sscanf(args, "%f%f%f", &skyboxr, &skyboxg, &skyboxb);
1268
1269     skyboxlightr = skyboxr;
1270     skyboxlightg = skyboxg;
1271     skyboxlightb = skyboxb;
1272
1273     SetUpLighting();
1274
1275     terrain.DoShadows();
1276     objects.DoShadows();
1277 }
1278
1279 static void ch_skylight(const char *args)
1280 {
1281     sscanf(args, "%f%f%f", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1282
1283     SetUpLighting();
1284
1285     terrain.DoShadows();
1286     objects.DoShadows();
1287 }
1288
1289 static void ch_skybox(const char *args)
1290 {
1291     skyboxtexture = !skyboxtexture;
1292
1293     SetUpLighting();
1294
1295     terrain.DoShadows();
1296     objects.DoShadows();
1297 }
1298
1299 static void cmd_dispatch(const string cmd)
1300 {
1301     int i, n_cmds = sizeof(cmd_names) / sizeof(cmd_names[0]);
1302
1303     for (i = 0; i < n_cmds; i++)
1304         if (cmd.substr(0, cmd.find(' ')) == string(cmd_names[i])) {
1305             cout << "|" << cmd.substr(cmd.find(' ') + 1) << "|" << endl;
1306             cmd_handlers[i](cmd.substr(cmd.find(' ') + 1).c_str());
1307             break;
1308         }
1309     emit_sound_np(i < n_cmds ? consolesuccesssound : consolefailsound);
1310 }
1311
1312 /********************> Tick() <*****/
1313 extern bool save_image(const char * fname);
1314 void Screenshot (void)
1315 {
1316     char temp[1024];
1317     time_t t = time(NULL);
1318     struct tm *tme = localtime(&t);
1319     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);
1320
1321 #if defined(_WIN32)
1322     mkdir("Screenshots");
1323 #else
1324     mkdir("Screenshots", S_IRWXU);
1325 #endif
1326
1327     save_image(temp);
1328 }
1329
1330 void Game::SetUpLighting()
1331 {
1332     if (environment == snowyenvironment)
1333         light.setColors(.65, .65, .7, .4, .4, .44);
1334     if (environment == desertenvironment)
1335         light.setColors(.95, .95, .95, .4, .35, .3);
1336     if (environment == grassyenvironment)
1337         light.setColors(.95, .95, 1, .4, .4, .44);
1338     if (!skyboxtexture)
1339         light.setColors(1, 1, 1, .4, .4, .4);
1340     float average;
1341     average = (skyboxlightr + skyboxlightg + skyboxlightb) / 3;
1342     light.color[0] *= (skyboxlightr + average) / 2;
1343     light.color[1] *= (skyboxlightg + average) / 2;
1344     light.color[2] *= (skyboxlightb + average) / 2;
1345     light.ambient[0] *= (skyboxlightr + average) / 2;
1346     light.ambient[1] *= (skyboxlightg + average) / 2;
1347     light.ambient[2] *= (skyboxlightb + average) / 2;
1348 }
1349
1350 int findPathDist(int start, int end)
1351 {
1352     int smallestcount, count, connected;
1353     int last, last2, last3, last4;
1354     int closest;
1355
1356     smallestcount = 1000;
1357     for (int i = 0; i < 50; i++) {
1358         count = 0;
1359         last = start;
1360         last2 = -1;
1361         last3 = -1;
1362         last4 = -1;
1363         while (last != end && count < 30) {
1364             closest = -1;
1365             for (int j = 0; j < numpathpoints; j++) {
1366                 if (j != last && j != last2 && j != last3 && j != last4) {
1367                     connected = 0;
1368                     if (numpathpointconnect[j])
1369                         for (int k = 0; k < numpathpointconnect[j]; k++) {
1370                             if (pathpointconnect[j][k] == last)connected = 1;
1371                         }
1372                     if (!connected)
1373                         if (numpathpointconnect[last])
1374                             for (int k = 0; k < numpathpointconnect[last]; k++) {
1375                                 if (pathpointconnect[last][k] == j)connected = 1;
1376                             }
1377                     if (connected)
1378                         if (closest == -1 || Random() % 2 == 0) {
1379                             closest = j;
1380                         }
1381                 }
1382             }
1383             last4 = last3;
1384             last3 = last2;
1385             last2 = last;
1386             last = closest;
1387             count++;
1388         }
1389         if (count < smallestcount)
1390             smallestcount = count;
1391     }
1392     return smallestcount;
1393 }
1394
1395 int Game::checkcollide(XYZ startpoint, XYZ endpoint)
1396 {
1397     static XYZ colpoint, colviewer, coltarget;
1398     static float minx, minz, maxx, maxz, miny, maxy;
1399
1400     minx = min(startpoint.x, endpoint.x) - 1;
1401     miny = min(startpoint.y, endpoint.y) - 1;
1402     minz = min(startpoint.z, endpoint.z) - 1;
1403     maxx = max(startpoint.x, endpoint.x) + 1;
1404     maxy = max(startpoint.y, endpoint.y) + 1;
1405     maxz = max(startpoint.z, endpoint.z) + 1;
1406
1407     for (int i = 0; i < objects.numobjects; i++) {
1408         if (     objects.position[i].x > minx - objects.model[i].boundingsphereradius &&
1409                  objects.position[i].x < maxx + objects.model[i].boundingsphereradius &&
1410                  objects.position[i].y > miny - objects.model[i].boundingsphereradius &&
1411                  objects.position[i].y < maxy + objects.model[i].boundingsphereradius &&
1412                  objects.position[i].z > minz - objects.model[i].boundingsphereradius &&
1413                  objects.position[i].z < maxz + objects.model[i].boundingsphereradius) {
1414             if (     objects.type[i] != treeleavestype &&
1415                      objects.type[i] != bushtype &&
1416                      objects.type[i] != firetype) {
1417                 colviewer = startpoint;
1418                 coltarget = endpoint;
1419                 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
1420                     return i;
1421             }
1422         }
1423     }
1424
1425     //if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)return 1000;
1426
1427     return -1;
1428 }
1429
1430 int Game::checkcollide(XYZ startpoint, XYZ endpoint, int what)
1431 {
1432     static XYZ colpoint, colviewer, coltarget;
1433     static float minx, minz, maxx, maxz, miny, maxy;
1434     static int i; //FIXME: see below
1435
1436     minx = min(startpoint.x, endpoint.x) - 1;
1437     miny = min(startpoint.y, endpoint.y) - 1;
1438     minz = min(startpoint.z, endpoint.z) - 1;
1439     maxx = max(startpoint.x, endpoint.x) + 1;
1440     maxy = max(startpoint.y, endpoint.y) + 1;
1441     maxz = max(startpoint.z, endpoint.z) + 1;
1442
1443     if (what != 1000) {
1444         if (     objects.position[what].x > minx - objects.model[what].boundingsphereradius &&
1445                  objects.position[what].x < maxx + objects.model[what].boundingsphereradius &&
1446                  objects.position[what].y > miny - objects.model[what].boundingsphereradius &&
1447                  objects.position[what].y < maxy + objects.model[what].boundingsphereradius &&
1448                  objects.position[what].z > minz - objects.model[what].boundingsphereradius &&
1449                  objects.position[what].z < maxz + objects.model[what].boundingsphereradius) {
1450             if (     objects.type[what] != treeleavestype &&
1451                      objects.type[what] != bushtype &&
1452                      objects.type[what] != firetype) {
1453                 colviewer = startpoint;
1454                 coltarget = endpoint;
1455                 //FIXME: i/what
1456                 if (objects.model[what].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[what], &objects.yaw[what]) != -1)
1457                     return i;
1458             }
1459         }
1460     }
1461
1462     if (what == 1000)
1463         if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
1464             return 1000;
1465
1466     return -1;
1467 }
1468
1469 void Setenvironment(int which)
1470 {
1471     LOGFUNC;
1472
1473     LOG(" Setting environment...");
1474
1475     float temptexdetail;
1476     environment = which;
1477
1478     pause_sound(stream_snowtheme);
1479     pause_sound(stream_grasstheme);
1480     pause_sound(stream_deserttheme);
1481     pause_sound(stream_wind);
1482     pause_sound(stream_desertambient);
1483
1484
1485     if (environment == snowyenvironment) {
1486         windvector = 0;
1487         windvector.z = 3;
1488         if (ambientsound)
1489             emit_stream_np(stream_wind);
1490
1491         objects.treetextureptr.load(":Data:Textures:snowtree.png", 0, 1);
1492         objects.bushtextureptr.load(":Data:Textures:bushsnow.png", 0, 1);
1493         objects.rocktextureptr.load(":Data:Textures:bouldersnow.jpg", 1, 0);
1494         objects.boxtextureptr.load(":Data:Textures:snowbox.jpg", 1, 0);
1495
1496         footstepsound = footstepsn1;
1497         footstepsound2 = footstepsn2;
1498         footstepsound3 = footstepst1;
1499         footstepsound4 = footstepst2;
1500
1501         terraintexture.load(":Data:Textures:snow.jpg", 1, 0);
1502         terraintexture2.load(":Data:Textures:rock.jpg", 1, 0);
1503
1504         //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1505
1506
1507
1508
1509         temptexdetail = texdetail;
1510         if (texdetail > 1)
1511             texdetail = 4;
1512         skybox->load(   ":Data:Textures:Skybox(snow):Front.jpg",
1513                         ":Data:Textures:Skybox(snow):Left.jpg",
1514                         ":Data:Textures:Skybox(snow):Back.jpg",
1515                         ":Data:Textures:Skybox(snow):Right.jpg",
1516                         ":Data:Textures:Skybox(snow):Up.jpg",
1517                         ":Data:Textures:Skybox(snow):Down.jpg");
1518
1519
1520
1521
1522         texdetail = temptexdetail;
1523     } else if (environment == desertenvironment) {
1524         windvector = 0;
1525         windvector.z = 2;
1526         objects.treetextureptr.load(":Data:Textures:deserttree.png", 0, 1);
1527         objects.bushtextureptr.load(":Data:Textures:bushdesert.png", 0, 1);
1528         objects.rocktextureptr.load(":Data:Textures:boulderdesert.jpg", 1, 0);
1529         objects.boxtextureptr.load(":Data:Textures:desertbox.jpg", 1, 0);
1530
1531
1532         if (ambientsound)
1533             emit_stream_np(stream_desertambient);
1534
1535         footstepsound = footstepsn1;
1536         footstepsound2 = footstepsn2;
1537         footstepsound3 = footstepsn1;
1538         footstepsound4 = footstepsn2;
1539
1540         terraintexture.load(":Data:Textures:sand.jpg", 1, 0);
1541         terraintexture2.load(":Data:Textures:sandslope.jpg", 1, 0);
1542
1543         //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1544
1545
1546
1547         temptexdetail = texdetail;
1548         if (texdetail > 1)
1549             texdetail = 4;
1550         skybox->load(   ":Data:Textures:Skybox(sand):Front.jpg",
1551                         ":Data:Textures:Skybox(sand):Left.jpg",
1552                         ":Data:Textures:Skybox(sand):Back.jpg",
1553                         ":Data:Textures:Skybox(sand):Right.jpg",
1554                         ":Data:Textures:Skybox(sand):Up.jpg",
1555                         ":Data:Textures:Skybox(sand):Down.jpg");
1556
1557
1558
1559
1560         texdetail = temptexdetail;
1561     } else if (environment == grassyenvironment) {
1562         windvector = 0;
1563         windvector.z = 2;
1564         objects.treetextureptr.load(":Data:Textures:tree.png", 0, 1);
1565         objects.bushtextureptr.load(":Data:Textures:bush.png", 0, 1);
1566         objects.rocktextureptr.load(":Data:Textures:boulder.jpg", 1, 0);
1567         objects.boxtextureptr.load(":Data:Textures:grassbox.jpg", 1, 0);
1568
1569         if (ambientsound)
1570             emit_stream_np(stream_wind, 100.);
1571
1572         footstepsound = footstepgr1;
1573         footstepsound2 = footstepgr2;
1574         footstepsound3 = footstepst1;
1575         footstepsound4 = footstepst2;
1576
1577         terraintexture.load(":Data:Textures:grassdirt.jpg", 1, 0);
1578         terraintexture2.load(":Data:Textures:mossrock.jpg", 1, 0);
1579
1580         //LoadTexture(":Data:Textures:detail.png",&terraintexture3,1);
1581
1582
1583
1584         temptexdetail = texdetail;
1585         if (texdetail > 1)
1586             texdetail = 4;
1587         skybox->load(   ":Data:Textures:Skybox(grass):Front.jpg",
1588                         ":Data:Textures:Skybox(grass):Left.jpg",
1589                         ":Data:Textures:Skybox(grass):Back.jpg",
1590                         ":Data:Textures:Skybox(grass):Right.jpg",
1591                         ":Data:Textures:Skybox(grass):Up.jpg",
1592                         ":Data:Textures:Skybox(grass):Down.jpg");
1593
1594
1595
1596         texdetail = temptexdetail;
1597     }
1598     temptexdetail = texdetail;
1599     texdetail = 1;
1600     terrain.load(":Data:Textures:heightmap.png");
1601
1602     texdetail = temptexdetail;
1603 }
1604
1605 void LoadCampaign()
1606 {
1607     if (!accountactive)
1608         return;
1609     ifstream ipstream(ConvertFileName((":Data:Campaigns:" + accountactive->getCurrentCampaign() + ".txt").c_str()));
1610     ipstream.ignore(256, ':');
1611     int numlevels;
1612     ipstream >> numlevels;
1613     campaignlevels.clear();
1614     for (int i = 0; i < numlevels; i++) {
1615         CampaignLevel cl;
1616         ipstream >> cl;
1617         campaignlevels.push_back(cl);
1618     }
1619     ipstream.close();
1620
1621     ifstream test(ConvertFileName((":Data:Textures:" + accountactive->getCurrentCampaign() + ":World.png").c_str()));
1622     if (test.good()) {
1623         Mainmenuitems[7].load((":Data:Textures:" + accountactive->getCurrentCampaign() + ":World.png").c_str(), 0, 0);
1624     } else {
1625         Mainmenuitems[7].load(":Data:Textures:World.png", 0, 0);
1626     }
1627
1628     if (accountactive->getCampaignChoicesMade() == 0) {
1629         accountactive->setCampaignScore(0);
1630         accountactive->resetFasttime();
1631     }
1632 }
1633
1634 vector<string> ListCampaigns()
1635 {
1636     DIR *campaigns = opendir(ConvertFileName(":Data:Campaigns"));
1637     struct dirent *campaign = NULL;
1638     if (!campaigns) {
1639         perror("Problem while loading campaigns");
1640         cerr << "campaign folder was : " << ConvertFileName(":Data:Campaigns") << endl;
1641         exit(EXIT_FAILURE);
1642     }
1643     vector<string> campaignNames;
1644     while ((campaign = readdir(campaigns)) != NULL) {
1645         string name(campaign->d_name);
1646         if (name.length() < 5)
1647             continue;
1648         if (!name.compare(name.length() - 4, 4, ".txt")) {
1649             campaignNames.push_back(name.substr(0, name.length() - 4));
1650         }
1651     }
1652     closedir(campaigns);
1653     return campaignNames;
1654 }
1655
1656 void Loadlevel(int which)
1657 {
1658     stealthloading = 0;
1659     whichlevel = which;
1660
1661     if (which == -1) {
1662         tutoriallevel = -1;
1663         Loadlevel("tutorial");
1664     } else if (which >= 0 && which <= 15) {
1665         char buf[32];
1666         snprintf(buf, 32, "map%d", which + 1); // challenges
1667         Loadlevel(buf);
1668     } else
1669         Loadlevel("mapsave");
1670 }
1671
1672 void Loadlevel(const char *name)
1673 {
1674     int templength;
1675     float lamefloat;
1676     static const char *pfx = ":Data:Maps:";
1677     char *buf;
1678
1679     float headprop, legprop, armprop, bodyprop;
1680
1681     LOGFUNC;
1682
1683     LOG(std::string("Loading level...") + name);
1684
1685     if (!gameon)
1686         visibleloading = 1;
1687     if (stealthloading)
1688         visibleloading = 0;
1689     if (!stillloading)
1690         loadtime = 0;
1691     gamestarted = 1;
1692
1693     numenvsounds = 0;
1694
1695     if (tutoriallevel != -1)
1696         tutoriallevel = 0;
1697     else
1698         tutoriallevel = 1;
1699
1700     if (tutoriallevel == 1)
1701         tutorialstage = 0;
1702     if (tutorialstage == 0) {
1703         tutorialstagetime = 0;
1704         tutorialmaxtime = 1;
1705     }
1706     loadingstuff = 1;
1707     pause_sound(whooshsound);
1708     pause_sound(stream_firesound);
1709
1710     // Change the map filename into something that is os specific
1711     buf = (char*) alloca(strlen(pfx) + strlen(name) + 1);
1712     sprintf(buf, "%s%s", pfx, name);
1713     const char *FixedFN = ConvertFileName(buf);
1714
1715     int mapvers;
1716     FILE *tfile;
1717     //~ char* buff=getcwd(NULL,0);
1718     //~ cout << buff << " " << FixedFN << endl;
1719     //~ free(buff);
1720     tfile = fopen( FixedFN, "rb" );
1721     if (tfile) {
1722         pause_sound(stream_firesound);
1723         scoreadded = 0;
1724         windialogue = false;
1725         hostiletime = 0;
1726         won = 0;
1727
1728         animation[bounceidleanim].Load((char *)"Idle", middleheight, neutral);
1729
1730         numdialogues = 0;
1731
1732         for (int i = 0; i < 20; i++)
1733             dialoguegonethrough[i] = 0;
1734
1735         indialogue = -1;
1736         cameramode = 0;
1737
1738         damagedealt = 0;
1739         damagetaken = 0;
1740
1741         if (accountactive)
1742             difficulty = accountactive->getDifficulty();
1743
1744         numhotspots = 0;
1745         currenthotspot = -1;
1746         bonustime = 1;
1747
1748         skyboxtexture = 1;
1749         skyboxr = 1;
1750         skyboxg = 1;
1751         skyboxb = 1;
1752
1753         freeze = 0;
1754         winfreeze = 0;
1755
1756         for (int i = 0; i < 100; i++)
1757             bonusnum[i] = 0;
1758
1759         numfalls = 0;
1760         numflipfail = 0;
1761         numseen = 0;
1762         numstaffattack = 0;
1763         numswordattack = 0;
1764         numknifeattack = 0;
1765         numunarmedattack = 0;
1766         numescaped = 0;
1767         numflipped = 0;
1768         numwallflipped = 0;
1769         numthrowkill = 0;
1770         numafterkill = 0;
1771         numreversals = 0;
1772         numattacks = 0;
1773         maxalarmed = 0;
1774         numresponded = 0;
1775
1776         bonustotal = startbonustotal;
1777         bonus = 0;
1778         gameon = 1;
1779         changedelay = 0;
1780         if (console) {
1781             emit_sound_np(consolesuccesssound);
1782             freeze = 0;
1783             console = false;
1784         }
1785
1786         if (!stealthloading) {
1787             terrain.numdecals = 0;
1788             Sprite::deleteSprites();
1789             for (int i = 0; i < objects.numobjects; i++)
1790                 objects.model[i].numdecals = 0;
1791
1792             int j = objects.numobjects;
1793             for (int i = 0; i < j; i++) {
1794                 objects.DeleteObject(0);
1795                 if (visibleloading)
1796                     LoadingScreen();
1797             }
1798
1799             for (int i = 0; i < subdivision; i++)
1800                 for (int j = 0; j < subdivision; j++)
1801                     terrain.patchobjectnum[i][j] = 0;
1802             if (visibleloading)
1803                 LoadingScreen();
1804         }
1805
1806         weapons.clear();
1807
1808         funpackf(tfile, "Bi", &mapvers);
1809         if (mapvers >= 15)
1810             funpackf(tfile, "Bi", &indemo);
1811         else
1812             indemo = 0;
1813         if (mapvers >= 5)
1814             funpackf(tfile, "Bi", &maptype);
1815         else
1816             maptype = mapkilleveryone;
1817         if (mapvers >= 6)
1818             funpackf(tfile, "Bi", &hostile);
1819         else
1820             hostile = 1;
1821         if (mapvers >= 4)
1822             funpackf(tfile, "Bf Bf", &viewdistance, &fadestart);
1823         else {
1824             viewdistance = 100;
1825             fadestart = .6;
1826         }
1827         if (mapvers >= 2)
1828             funpackf(tfile, "Bb Bf Bf Bf", &skyboxtexture, &skyboxr, &skyboxg, &skyboxb);
1829         else {
1830             skyboxtexture = 1;
1831             skyboxr = 1;
1832             skyboxg = 1;
1833             skyboxb = 1;
1834         }
1835         if (mapvers >= 10)
1836             funpackf(tfile, "Bf Bf Bf", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1837         else {
1838             skyboxlightr = skyboxr;
1839             skyboxlightg = skyboxg;
1840             skyboxlightb = skyboxb;
1841         }
1842         if (!stealthloading)
1843             funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &Person::players[0]->coords.x, &Person::players[0]->coords.y, &Person::players[0]->coords.z, &Person::players[0]->yaw, &Person::players[0]->targetyaw, &Person::players[0]->num_weapons);
1844         if (stealthloading)
1845             funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat, &lamefloat, &lamefloat, &lamefloat, &lamefloat, &Person::players[0]->num_weapons);
1846         Person::players[0]->originalcoords = Person::players[0]->coords;
1847         if (Person::players[0]->num_weapons > 0 && Person::players[0]->num_weapons < 5)
1848             for (int j = 0; j < Person::players[0]->num_weapons; j++) {
1849                 Person::players[0]->weaponids[j] = weapons.size();
1850                 int type;
1851                 funpackf(tfile, "Bi", &type);
1852                 weapons.push_back(Weapon(type, 0));
1853             }
1854
1855         if (visibleloading)
1856             LoadingScreen();
1857
1858         funpackf(tfile, "Bf Bf Bf", &Person::players[0]->armorhead, &Person::players[0]->armorhigh, &Person::players[0]->armorlow);
1859         funpackf(tfile, "Bf Bf Bf", &Person::players[0]->protectionhead, &Person::players[0]->protectionhigh, &Person::players[0]->protectionlow);
1860         funpackf(tfile, "Bf Bf Bf", &Person::players[0]->metalhead, &Person::players[0]->metalhigh, &Person::players[0]->metallow);
1861         funpackf(tfile, "Bf Bf", &Person::players[0]->power, &Person::players[0]->speedmult);
1862
1863         funpackf(tfile, "Bi", &Person::players[0]->numclothes);
1864
1865         if (mapvers >= 9)
1866             funpackf(tfile, "Bi Bi", &Person::players[0]->whichskin, &Person::players[0]->creature);
1867         else {
1868             Person::players[0]->whichskin = 0;
1869             Person::players[0]->creature = rabbittype;
1870         }
1871
1872         Person::players[0]->lastattack = -1;
1873         Person::players[0]->lastattack2 = -1;
1874         Person::players[0]->lastattack3 = -1;
1875
1876         //dialogues
1877         if (mapvers >= 8) {
1878             funpackf(tfile, "Bi", &numdialogues);
1879             for (int k = 0; k < numdialogues; k++) {
1880                 funpackf(tfile, "Bi", &numdialogueboxes[k]);
1881                 funpackf(tfile, "Bi", &dialoguetype[k]);
1882                 for (int l = 0; l < 10; l++) {
1883                     funpackf(tfile, "Bf Bf Bf", &participantlocation[k][l].x, &participantlocation[k][l].y, &participantlocation[k][l].z);
1884                     funpackf(tfile, "Bf", &participantyaw[k][l]);
1885                 }
1886                 for (int l = 0; l < numdialogueboxes[k]; l++) {
1887                     funpackf(tfile, "Bi", &dialogueboxlocation[k][l]);
1888                     funpackf(tfile, "Bf", &dialogueboxcolor[k][l][0]);
1889                     funpackf(tfile, "Bf", &dialogueboxcolor[k][l][1]);
1890                     funpackf(tfile, "Bf", &dialogueboxcolor[k][l][2]);
1891                     funpackf(tfile, "Bi", &dialogueboxsound[k][l]);
1892
1893                     funpackf(tfile, "Bi", &templength);
1894                     if (templength > 128 || templength <= 0)
1895                         templength = 128;
1896                     int m;
1897                     for (m = 0; m < templength; m++) {
1898                         funpackf(tfile, "Bb", &dialoguetext[k][l][m]);
1899                         if (dialoguetext[k][l][m] == '\0')
1900                             break;
1901                     }
1902                     dialoguetext[k][l][m] = 0;
1903
1904                     funpackf(tfile, "Bi", &templength);
1905                     if (templength > 64 || templength <= 0)
1906                         templength = 64;
1907                     for (m = 0; m < templength; m++) {
1908                         funpackf(tfile, "Bb", &dialoguename[k][l][m]);
1909                         if (dialoguename[k][l][m] == '\0')
1910                             break;
1911                     }
1912                     dialoguename[k][l][m] = 0;
1913                     funpackf(tfile, "Bf Bf Bf", &dialoguecamera[k][l].x, &dialoguecamera[k][l].y, &dialoguecamera[k][l].z);
1914                     funpackf(tfile, "Bi", &participantfocus[k][l]);
1915                     funpackf(tfile, "Bi", &participantaction[k][l]);
1916
1917                     for (m = 0; m < 10; m++)
1918                         funpackf(tfile, "Bf Bf Bf", &participantfacing[k][l][m].x, &participantfacing[k][l][m].y, &participantfacing[k][l][m].z);
1919
1920                     funpackf(tfile, "Bf Bf", &dialoguecamerayaw[k][l], &dialoguecamerapitch[k][l]);
1921                 }
1922             }
1923         } else
1924             numdialogues = 0;
1925
1926         for (int k = 0; k < Person::players[0]->numclothes; k++) {
1927             funpackf(tfile, "Bi", &templength);
1928             for (int l = 0; l < templength; l++)
1929                 funpackf(tfile, "Bb", &Person::players[0]->clothes[k][l]);
1930             Person::players[0]->clothes[k][templength] = '\0';
1931             funpackf(tfile, "Bf Bf Bf", &Person::players[0]->clothestintr[k], &Person::players[0]->clothestintg[k], &Person::players[0]->clothestintb[k]);
1932         }
1933
1934         funpackf(tfile, "Bi", &environment);
1935
1936         funpackf(tfile, "Bi", &objects.numobjects);
1937         for (int i = 0; i < objects.numobjects; i++) {
1938             funpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", &objects.type[i], &objects.yaw[i], &objects.pitch[i], &objects.position[i].x, &objects.position[i].y, &objects.position[i].z, &objects.scale[i]);
1939             if (objects.type[i] == treeleavestype)
1940                 objects.scale[i] = objects.scale[i - 1];
1941         }
1942
1943         if (mapvers >= 7) {
1944             funpackf(tfile, "Bi", &numhotspots);
1945             for (int i = 0; i < numhotspots; i++) {
1946                 funpackf(tfile, "Bi Bf Bf Bf Bf", &hotspottype[i], &hotspotsize[i], &hotspot[i].x, &hotspot[i].y, &hotspot[i].z);
1947                 funpackf(tfile, "Bi", &templength);
1948                 if (templength)
1949                     for (int l = 0; l < templength; l++)
1950                         funpackf(tfile, "Bb", &hotspottext[i][l]);
1951                 hotspottext[i][templength] = '\0';
1952                 if (hotspottype[i] == -111)
1953                     indemo = 1;
1954             }
1955         } else
1956             numhotspots = 0;
1957
1958         if (visibleloading)
1959             LoadingScreen();
1960
1961         if (!stealthloading) {
1962             objects.center = 0;
1963             for (int i = 0; i < objects.numobjects; i++)
1964                 objects.center += objects.position[i];
1965             objects.center /= objects.numobjects;
1966
1967
1968             if (visibleloading)
1969                 LoadingScreen();
1970
1971             float maxdistance = 0;
1972             float tempdist;
1973             //~ int whichclosest;
1974             for (int i = 0; i < objects.numobjects; i++) {
1975                 tempdist = distsq(&objects.center, &objects.position[i]);
1976                 if (tempdist > maxdistance) {
1977                     //~ whichclosest=i;
1978                     maxdistance = tempdist;
1979                 }
1980             }
1981             objects.radius = fast_sqrt(maxdistance);
1982         }
1983
1984         if (visibleloading)
1985             LoadingScreen();
1986         //mapcenter=objects.center;
1987         //mapradius=objects.radius;
1988
1989         funpackf(tfile, "Bi", &numplayers);
1990         int howmanyremoved = 0;
1991         bool removeanother = 0;
1992         if (numplayers > 1 && numplayers < maxplayers) {
1993             for (int i = 1; i < numplayers; i++) {
1994                 Person::players.push_back(shared_ptr<Person>(new Person()));
1995                 if (visibleloading)
1996                     LoadingScreen();
1997                 removeanother = 0;
1998
1999                 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &Person::players[i - howmanyremoved]->whichskin, &Person::players[i - howmanyremoved]->creature, &Person::players[i - howmanyremoved]->coords.x, &Person::players[i - howmanyremoved]->coords.y, &Person::players[i - howmanyremoved]->coords.z, &Person::players[i - howmanyremoved]->num_weapons);
2000                 if (mapvers >= 5)
2001                     funpackf(tfile, "Bi", &Person::players[i - howmanyremoved]->howactive);
2002                 else
2003                     Person::players[i - howmanyremoved]->howactive = typeactive;
2004                 if (mapvers >= 3)
2005                     funpackf(tfile, "Bf", &Person::players[i - howmanyremoved]->scale);
2006                 else
2007                     Person::players[i - howmanyremoved]->scale = -1;
2008                 if (mapvers >= 11)
2009                     funpackf(tfile, "Bb", &Person::players[i - howmanyremoved]->immobile);
2010                 else
2011                     Person::players[i - howmanyremoved]->immobile = 0;
2012                 if (mapvers >= 12)
2013                     funpackf(tfile, "Bf", &Person::players[i - howmanyremoved]->yaw);
2014                 else
2015                     Person::players[i - howmanyremoved]->yaw = 0;
2016                 Person::players[i - howmanyremoved]->targetyaw = Person::players[i - howmanyremoved]->yaw;
2017                 if (Person::players[i - howmanyremoved]->num_weapons < 0 || Person::players[i - howmanyremoved]->num_weapons > 5) {
2018                     removeanother = 1;
2019                     howmanyremoved++;
2020                 }
2021                 if (!removeanother) {
2022                     if (Person::players[i - howmanyremoved]->num_weapons > 0 && Person::players[i - howmanyremoved]->num_weapons < 5) {
2023                         for (int j = 0; j < Person::players[i - howmanyremoved]->num_weapons; j++) {
2024                             Person::players[i - howmanyremoved]->weaponids[j] = weapons.size();
2025                             int type;
2026                             funpackf(tfile, "Bi", &type);
2027                             weapons.push_back(Weapon(type, i));
2028                         }
2029                     }
2030                     funpackf(tfile, "Bi", &Person::players[i - howmanyremoved]->numwaypoints);
2031                     //Person::players[i-howmanyremoved]->numwaypoints=10;
2032                     for (int j = 0; j < Person::players[i - howmanyremoved]->numwaypoints; j++) {
2033                         funpackf(tfile, "Bf", &Person::players[i - howmanyremoved]->waypoints[j].x);
2034                         funpackf(tfile, "Bf", &Person::players[i - howmanyremoved]->waypoints[j].y);
2035                         funpackf(tfile, "Bf", &Person::players[i - howmanyremoved]->waypoints[j].z);
2036                         if (mapvers >= 5)
2037                             funpackf(tfile, "Bi", &Person::players[i - howmanyremoved]->waypointtype[j]);
2038                         else
2039                             Person::players[i - howmanyremoved]->waypointtype[j] = wpkeepwalking;
2040                     }
2041
2042                     funpackf(tfile, "Bi", &Person::players[i - howmanyremoved]->waypoint);
2043                     if (Person::players[i - howmanyremoved]->waypoint > Person::players[i - howmanyremoved]->numwaypoints - 1)
2044                         Person::players[i - howmanyremoved]->waypoint = 0;
2045
2046                     funpackf(tfile, "Bf Bf Bf", &Person::players[i - howmanyremoved]->armorhead, &Person::players[i - howmanyremoved]->armorhigh, &Person::players[i - howmanyremoved]->armorlow);
2047                     funpackf(tfile, "Bf Bf Bf", &Person::players[i - howmanyremoved]->protectionhead, &Person::players[i - howmanyremoved]->protectionhigh, &Person::players[i - howmanyremoved]->protectionlow);
2048                     funpackf(tfile, "Bf Bf Bf", &Person::players[i - howmanyremoved]->metalhead, &Person::players[i - howmanyremoved]->metalhigh, &Person::players[i - howmanyremoved]->metallow);
2049                     funpackf(tfile, "Bf Bf", &Person::players[i - howmanyremoved]->power, &Person::players[i - howmanyremoved]->speedmult);
2050
2051                     if (mapvers >= 4)
2052                         funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
2053                     else {
2054                         headprop = 1;
2055                         bodyprop = 1;
2056                         armprop = 1;
2057                         legprop = 1;
2058                     }
2059                     if (Person::players[i - howmanyremoved]->creature == wolftype) {
2060                         Person::players[i - howmanyremoved]->proportionhead = 1.1 * headprop;
2061                         Person::players[i - howmanyremoved]->proportionbody = 1.1 * bodyprop;
2062                         Person::players[i - howmanyremoved]->proportionarms = 1.1 * armprop;
2063                         Person::players[i - howmanyremoved]->proportionlegs = 1.1 * legprop;
2064                     }
2065
2066                     if (Person::players[i - howmanyremoved]->creature == rabbittype) {
2067                         Person::players[i - howmanyremoved]->proportionhead = 1.2 * headprop;
2068                         Person::players[i - howmanyremoved]->proportionbody = 1.05 * bodyprop;
2069                         Person::players[i - howmanyremoved]->proportionarms = 1.00 * armprop;
2070                         Person::players[i - howmanyremoved]->proportionlegs = 1.1 * legprop;
2071                         Person::players[i - howmanyremoved]->proportionlegs.y = 1.05 * legprop;
2072                     }
2073
2074                     funpackf(tfile, "Bi", &Person::players[i - howmanyremoved]->numclothes);
2075                     if (Person::players[i - howmanyremoved]->numclothes) {
2076                         for (int k = 0; k < Person::players[i - howmanyremoved]->numclothes; k++) {
2077                             int templength;
2078                             funpackf(tfile, "Bi", &templength);
2079                             for (int l = 0; l < templength; l++)
2080                                 funpackf(tfile, "Bb", &Person::players[i - howmanyremoved]->clothes[k][l]);
2081                             Person::players[i - howmanyremoved]->clothes[k][templength] = '\0';
2082                             funpackf(tfile, "Bf Bf Bf", &Person::players[i - howmanyremoved]->clothestintr[k], &Person::players[i - howmanyremoved]->clothestintg[k], &Person::players[i - howmanyremoved]->clothestintb[k]);
2083                         }
2084                     }
2085                 }
2086             }
2087         }
2088         if (visibleloading)
2089             LoadingScreen();
2090
2091         numplayers -= howmanyremoved;
2092         funpackf(tfile, "Bi", &numpathpoints);
2093         if (numpathpoints > 30 || numpathpoints < 0)
2094             numpathpoints = 0;
2095         for (int j = 0; j < numpathpoints; j++) {
2096             funpackf(tfile, "Bf Bf Bf Bi", &pathpoint[j].x, &pathpoint[j].y, &pathpoint[j].z, &numpathpointconnect[j]);
2097             for (int k = 0; k < numpathpointconnect[j]; k++) {
2098                 funpackf(tfile, "Bi", &pathpointconnect[j][k]);
2099             }
2100         }
2101         if (visibleloading)
2102             LoadingScreen();
2103
2104         funpackf(tfile, "Bf Bf Bf Bf", &mapcenter.x, &mapcenter.y, &mapcenter.z, &mapradius);
2105
2106         SetUpLighting();
2107         if (environment != oldenvironment)
2108             Setenvironment(environment);
2109         oldenvironment = environment;
2110
2111         if (!stealthloading) {
2112             int j = objects.numobjects;
2113             objects.numobjects = 0;
2114             for (int i = 0; i < j; i++) {
2115                 objects.MakeObject(objects.type[i], objects.position[i], objects.yaw[i], objects.pitch[i], objects.scale[i]);
2116                 if (visibleloading)
2117                     LoadingScreen();
2118             }
2119
2120             terrain.DoShadows();
2121             if (visibleloading)
2122                 LoadingScreen();
2123             objects.DoShadows();
2124             if (visibleloading)
2125                 LoadingScreen();
2126         }
2127
2128         fclose(tfile);
2129
2130         if (numplayers > maxplayers - 1)
2131             numplayers = maxplayers - 1;
2132         for (int i = 0; i < numplayers; i++) {
2133             if (visibleloading)
2134                 LoadingScreen();
2135             Person::players[i]->burnt = 0;
2136             Person::players[i]->bled = 0;
2137             Person::players[i]->onfire = 0;
2138             if (i == 0 || Person::players[i]->scale < 0)
2139                 Person::players[i]->scale = .2;
2140             Person::players[i]->skeleton.free = 0;
2141             Person::players[i]->skeleton.id = i;
2142             if (i == 0 && mapvers < 9)
2143                 Person::players[i]->creature = rabbittype;
2144             if (Person::players[i]->creature != wolftype) {
2145                 Person::players[i]->skeleton.Load(
2146                     (char *)":Data:Skeleton:Basic Figure",
2147                     (char *)":Data:Skeleton:Basic Figurelow",
2148                     (char *)":Data:Skeleton:Rabbitbelt",
2149                     (char *)":Data:Models:Body.solid",
2150                     (char *)":Data:Models:Body2.solid",
2151                     (char *)":Data:Models:Body3.solid",
2152                     (char *)":Data:Models:Body4.solid",
2153                     (char *)":Data:Models:Body5.solid",
2154                     (char *)":Data:Models:Body6.solid",
2155                     (char *)":Data:Models:Body7.solid",
2156                     (char *)":Data:Models:Bodylow.solid",
2157                     (char *)":Data:Models:Belt.solid", 0);
2158             } else {
2159                 if (Person::players[i]->creature != wolftype) {
2160                     Person::players[i]->skeleton.Load(
2161                         (char *)":Data:Skeleton:Basic Figure",
2162                         (char *)":Data:Skeleton:Basic Figurelow",
2163                         (char *)":Data:Skeleton:Rabbitbelt",
2164                         (char *)":Data:Models:Body.solid",
2165                         (char *)":Data:Models:Body2.solid",
2166                         (char *)":Data:Models:Body3.solid",
2167                         (char *)":Data:Models:Body4.solid",
2168                         (char *)":Data:Models:Body5.solid",
2169                         (char *)":Data:Models:Body6.solid",
2170                         (char *)":Data:Models:Body7.solid",
2171                         (char *)":Data:Models:Bodylow.solid",
2172                         (char *)":Data:Models:Belt.solid", 1);
2173                     Person::players[i]->skeleton.drawmodelclothes.textureptr.load(":Data:Textures:Belt.png", 1, 1);
2174                 }
2175                 if (Person::players[i]->creature == wolftype) {
2176                     Person::players[i]->skeleton.Load(
2177                         (char *)":Data:Skeleton:Basic Figure Wolf",
2178                         (char *)":Data:Skeleton:Basic Figure Wolf Low",
2179                         (char *)":Data:Skeleton:Rabbitbelt",
2180                         (char *)":Data:Models:Wolf.solid",
2181                         (char *)":Data:Models:Wolf2.solid",
2182                         (char *)":Data:Models:Wolf3.solid",
2183                         (char *)":Data:Models:Wolf4.solid",
2184                         (char *)":Data:Models:Wolf5.solid",
2185                         (char *)":Data:Models:Wolf6.solid",
2186                         (char *)":Data:Models:Wolf7.solid",
2187                         (char *)":Data:Models:Wolflow.solid",
2188                         (char *)":Data:Models:Belt.solid", 0);
2189                 }
2190             }
2191
2192             Person::players[i]->skeleton.drawmodel.textureptr.load(creatureskin[Person::players[i]->creature][Person::players[i]->whichskin], 1, &Person::players[i]->skeleton.skinText[0], &Person::players[i]->skeleton.skinsize);
2193
2194             if (Person::players[i]->numclothes) {
2195                 for (int j = 0; j < Person::players[i]->numclothes; j++) {
2196                     tintr = Person::players[i]->clothestintr[j];
2197                     tintg = Person::players[i]->clothestintg[j];
2198                     tintb = Person::players[i]->clothestintb[j];
2199                     AddClothes((char *)Person::players[i]->clothes[j], &Person::players[i]->skeleton.skinText[0]);
2200                 }
2201                 Person::players[i]->DoMipmaps();
2202             }
2203
2204             Person::players[i]->animCurrent = bounceidleanim;
2205             Person::players[i]->animTarget = bounceidleanim;
2206             Person::players[i]->frameCurrent = 0;
2207             Person::players[i]->frameTarget = 1;
2208             Person::players[i]->target = 0;
2209             Person::players[i]->speed = 1 + (float)(Random() % 100) / 1000;
2210             if (difficulty == 0)
2211                 Person::players[i]->speed -= .2;
2212             if (difficulty == 1)
2213                 Person::players[i]->speed -= .1;
2214
2215             Person::players[i]->velocity = 0;
2216             Person::players[i]->oldcoords = Person::players[i]->coords;
2217             Person::players[i]->realoldcoords = Person::players[i]->coords;
2218
2219             Person::players[i]->id = i;
2220             Person::players[i]->skeleton.id = i;
2221             Person::players[i]->updatedelay = 0;
2222             Person::players[i]->normalsupdatedelay = 0;
2223
2224             Person::players[i]->aitype = passivetype;
2225             Person::players[i]->madskills = 0;
2226
2227             if (i == 0) {
2228                 Person::players[i]->proportionhead = 1.2;
2229                 Person::players[i]->proportionbody = 1.05;
2230                 Person::players[i]->proportionarms = 1.00;
2231                 Person::players[i]->proportionlegs = 1.1;
2232                 Person::players[i]->proportionlegs.y = 1.05;
2233             }
2234             Person::players[i]->headless = 0;
2235             Person::players[i]->currentoffset = 0;
2236             Person::players[i]->targetoffset = 0;
2237
2238             Person::players[i]->damagetolerance = 200;
2239
2240             if (Person::players[i]->creature == wolftype) {
2241                 if (i == 0 || Person::players[i]->scale < 0)
2242                     Person::players[i]->scale = .23;
2243                 Person::players[i]->damagetolerance = 300;
2244             }
2245
2246             if (visibleloading)
2247                 LoadingScreen();
2248             if (cellophane) {
2249                 Person::players[i]->proportionhead.z = 0;
2250                 Person::players[i]->proportionbody.z = 0;
2251                 Person::players[i]->proportionarms.z = 0;
2252                 Person::players[i]->proportionlegs.z = 0;
2253             }
2254
2255             Person::players[i]->tempanimation.Load((char *)"Tempanim", 0, 0);
2256
2257             Person::players[i]->headmorphness = 0;
2258             Person::players[i]->targetheadmorphness = 1;
2259             Person::players[i]->headmorphstart = 0;
2260             Person::players[i]->headmorphend = 0;
2261
2262             Person::players[i]->pausetime = 0;
2263
2264             Person::players[i]->dead = 0;
2265             Person::players[i]->jumppower = 5;
2266             Person::players[i]->damage = 0;
2267             Person::players[i]->permanentdamage = 0;
2268             Person::players[i]->superpermanentdamage = 0;
2269
2270             Person::players[i]->forwardkeydown = 0;
2271             Person::players[i]->leftkeydown = 0;
2272             Person::players[i]->backkeydown = 0;
2273             Person::players[i]->rightkeydown = 0;
2274             Person::players[i]->jumpkeydown = 0;
2275             Person::players[i]->crouchkeydown = 0;
2276             Person::players[i]->throwkeydown = 0;
2277
2278             Person::players[i]->collided = -10;
2279             Person::players[i]->loaded = 1;
2280             Person::players[i]->bloodloss = 0;
2281             Person::players[i]->weaponactive = -1;
2282             Person::players[i]->weaponstuck = -1;
2283             Person::players[i]->bleeding = 0;
2284             Person::players[i]->deathbleeding = 0;
2285             Person::players[i]->stunned = 0;
2286             Person::players[i]->hasvictim = 0;
2287             Person::players[i]->wentforweapon = 0;
2288         }
2289
2290         Person::players[0]->aitype = playercontrolled;
2291         Person::players[0]->weaponactive = -1;
2292
2293         if (difficulty == 1)
2294             Person::players[0]->power = 1 / .9;
2295
2296         if (difficulty == 0)
2297             Person::players[0]->power = 1 / .8;
2298
2299         if (difficulty == 1)
2300             Person::players[0]->damagetolerance = 250;
2301         if (difficulty == 0)
2302             Person::players[0]->damagetolerance = 300;
2303         if (difficulty == 0)
2304             Person::players[0]->armorhead *= 1.5;
2305         if (difficulty == 0)
2306             Person::players[0]->armorhigh *= 1.5;
2307         if (difficulty == 0)
2308             Person::players[0]->armorlow *= 1.5;
2309         cameraloc = Person::players[0]->coords;
2310         cameraloc.y += 5;
2311         yaw = Person::players[0]->yaw;
2312
2313         hawkcoords = Person::players[0]->coords;
2314         hawkcoords.y += 30;
2315
2316         if (visibleloading)
2317             LoadingScreen();
2318
2319         LOG("Starting background music...");
2320
2321         OPENAL_StopSound(OPENAL_ALL);
2322         if (environment == snowyenvironment) {
2323             if (ambientsound)
2324                 emit_stream_np(stream_wind);
2325         } else if (environment == desertenvironment) {
2326             if (ambientsound)
2327                 emit_stream_np(stream_desertambient);
2328         } else if (environment == grassyenvironment) {
2329             if (ambientsound)
2330                 emit_stream_np(stream_wind, 100.);
2331         }
2332         oldmusicvolume[0] = 0;
2333         oldmusicvolume[1] = 0;
2334         oldmusicvolume[2] = 0;
2335         oldmusicvolume[3] = 0;
2336
2337         if (!firstload)
2338             firstload = 1;
2339     } else {
2340         perror("Problem");
2341     }
2342     leveltime = 0;
2343     loadingstuff = 0;
2344     visibleloading = 0;
2345 }
2346
2347 void doTutorial()
2348 {
2349     if (tutorialstagetime > tutorialmaxtime) {
2350         tutorialstage++;
2351         tutorialsuccess = 0;
2352         if (tutorialstage <= 1) {
2353             canattack = 0;
2354             cananger = 0;
2355             reversaltrain = 0;
2356         }
2357         switch (tutorialstage) {
2358         case 1:
2359             tutorialmaxtime = 5;
2360             break;
2361         case 2:
2362             tutorialmaxtime = 2;
2363             break;
2364         case 3:
2365             tutorialmaxtime = 600;
2366             break;
2367         case 4:
2368             tutorialmaxtime = 1000;
2369             break;
2370         case 5:
2371             tutorialmaxtime = 600;
2372             break;
2373         case 6:
2374             tutorialmaxtime = 600;
2375             break;
2376         case 7:
2377             tutorialmaxtime = 600;
2378             break;
2379         case 8:
2380             tutorialmaxtime = 600;
2381             break;
2382         case 9:
2383             tutorialmaxtime = 600;
2384             break;
2385         case 10:
2386             tutorialmaxtime = 2;
2387             break;
2388         case 11:
2389             tutorialmaxtime = 1000;
2390             break;
2391         case 12:
2392             tutorialmaxtime = 1000;
2393             break;
2394         case 13:
2395             tutorialmaxtime = 2;
2396             break;
2397         case 14: {
2398             tutorialmaxtime = 3;
2399
2400             XYZ temp, temp2;
2401
2402             temp.x = 1011;
2403             temp.y = 84;
2404             temp.z = 491;
2405             temp2.x = 1025;
2406             temp2.y = 75;
2407             temp2.z = 447;
2408
2409             Person::players[1]->coords = (temp + temp2) / 2;
2410
2411             emit_sound_at(fireendsound, Person::players[1]->coords);
2412
2413             for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
2414                 if (Random() % 2 == 0) {
2415                     if (!Person::players[1]->skeleton.free)
2416                         temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
2417                     if (Person::players[1]->skeleton.free)
2418                         temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
2419                     if (!Person::players[1]->skeleton.free)
2420                         temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
2421                     if (Person::players[1]->skeleton.free)
2422                         temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
2423                     Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
2424                 }
2425             }
2426         }
2427         break;
2428         case 15:
2429             tutorialmaxtime = 500;
2430             break;
2431         case 16:
2432             tutorialmaxtime = 500;
2433             break;
2434         case 17:
2435             tutorialmaxtime = 500;
2436             break;
2437         case 18:
2438             tutorialmaxtime = 500;
2439             break;
2440         case 19:
2441             tutorialstage = 20;
2442             //tutorialmaxtime=500;
2443             break;
2444         case 20:
2445             tutorialmaxtime = 500;
2446             break;
2447         case 21:
2448             tutorialmaxtime = 500;
2449             if (bonus == cannon) {
2450                 bonus = Slicebonus;
2451                 againbonus = 1;
2452             } else
2453                 againbonus = 0;
2454             break;
2455         case 22:
2456             tutorialmaxtime = 500;
2457             break;
2458         case 23:
2459             tutorialmaxtime = 500;
2460             break;
2461         case 24:
2462             tutorialmaxtime = 500;
2463             break;
2464         case 25:
2465             tutorialmaxtime = 500;
2466             break;
2467         case 26:
2468             tutorialmaxtime = 2;
2469             break;
2470         case 27:
2471             tutorialmaxtime = 4;
2472             reversaltrain = 1;
2473             cananger = 1;
2474             Person::players[1]->aitype = attacktypecutoff;
2475             break;
2476         case 28:
2477             tutorialmaxtime = 400;
2478             break;
2479         case 29:
2480             tutorialmaxtime = 400;
2481             Person::players[0]->escapednum = 0;
2482             break;
2483         case 30:
2484             tutorialmaxtime = 4;
2485             reversaltrain = 0;
2486             cananger = 0;
2487             Person::players[1]->aitype = passivetype;
2488             break;
2489         case 31:
2490             tutorialmaxtime = 13;
2491             break;
2492         case 32:
2493             tutorialmaxtime = 8;
2494             break;
2495         case 33:
2496             tutorialmaxtime = 400;
2497             cananger = 1;
2498             canattack = 1;
2499             Person::players[1]->aitype = attacktypecutoff;
2500             break;
2501         case 34:
2502             tutorialmaxtime = 400;
2503             break;
2504         case 35:
2505             tutorialmaxtime = 400;
2506             break;
2507         case 36:
2508             tutorialmaxtime = 2;
2509             reversaltrain = 0;
2510             cananger = 0;
2511             Person::players[1]->aitype = passivetype;
2512             break;
2513         case 37:
2514             damagedealt = 0;
2515             damagetaken = 0;
2516             tutorialmaxtime = 50;
2517             cananger = 1;
2518             canattack = 1;
2519             Person::players[1]->aitype = attacktypecutoff;
2520             break;
2521         case 38:
2522             tutorialmaxtime = 4;
2523             canattack = 0;
2524             cananger = 0;
2525             Person::players[1]->aitype = passivetype;
2526             break;
2527         case 39: {
2528             XYZ temp, temp2;
2529
2530             temp.x = 1011;
2531             temp.y = 84;
2532             temp.z = 491;
2533             temp2.x = 1025;
2534             temp2.y = 75;
2535             temp2.z = 447;
2536
2537             Weapon w(knife, -1);
2538             w.position = (temp + temp2) / 2;
2539             w.tippoint = (temp + temp2) / 2;
2540
2541             w.velocity = 0.1;
2542             w.tipvelocity = 0.1;
2543             w.missed = 1;
2544             w.hitsomething = 0;
2545             w.freetime = 0;
2546             w.firstfree = 1;
2547             w.physics = 1;
2548
2549             weapons.push_back(w);
2550         }
2551         break;
2552         case 40:
2553             tutorialmaxtime = 300;
2554             break;
2555         case 41:
2556             tutorialmaxtime = 300;
2557             break;
2558         case 42:
2559             tutorialmaxtime = 8;
2560             break;
2561         case 43:
2562             tutorialmaxtime = 300;
2563             break;
2564         case 44:
2565             weapons[0].owner = 1;
2566             Person::players[0]->weaponactive = -1;
2567             Person::players[0]->num_weapons = 0;
2568             Person::players[1]->weaponactive = 0;
2569             Person::players[1]->num_weapons = 1;
2570             Person::players[1]->weaponids[0] = 0;
2571
2572             cananger = 1;
2573             canattack = 1;
2574             Person::players[1]->aitype = attacktypecutoff;
2575
2576             tutorialmaxtime = 300;
2577             break;
2578         case 45:
2579             weapons[0].owner = 1;
2580             Person::players[0]->weaponactive = -1;
2581             Person::players[0]->num_weapons = 0;
2582             Person::players[1]->weaponactive = 0;
2583             Person::players[1]->num_weapons = 1;
2584             Person::players[1]->weaponids[0] = 0;
2585
2586             tutorialmaxtime = 300;
2587             break;
2588         case 46:
2589             weapons[0].owner = 1;
2590             Person::players[0]->weaponactive = -1;
2591             Person::players[0]->num_weapons = 0;
2592             Person::players[1]->weaponactive = 0;
2593             Person::players[1]->num_weapons = 1;
2594             Person::players[1]->weaponids[0] = 0;
2595
2596             weapons[0].setType(sword);
2597
2598             tutorialmaxtime = 300;
2599             break;
2600         case 47: {
2601             tutorialmaxtime = 10;
2602
2603             XYZ temp, temp2;
2604
2605             temp.x = 1011;
2606             temp.y = 84;
2607             temp.z = 491;
2608             temp2.x = 1025;
2609             temp2.y = 75;
2610             temp2.z = 447;
2611
2612             Weapon w(sword, -1);
2613             w.position = (temp + temp2) / 2;
2614             w.tippoint = (temp + temp2) / 2;
2615
2616             w.velocity = 0.1;
2617             w.tipvelocity = 0.1;
2618             w.missed = 1;
2619             w.hitsomething = 0;
2620             w.freetime = 0;
2621             w.firstfree = 1;
2622             w.physics = 1;
2623
2624             weapons.push_back(w);
2625
2626             weapons[0].owner = 1;
2627             weapons[1].owner = 0;
2628             Person::players[0]->weaponactive = 0;
2629             Person::players[0]->num_weapons = 1;
2630             Person::players[0]->weaponids[0] = 1;
2631             Person::players[1]->weaponactive = 0;
2632             Person::players[1]->num_weapons = 1;
2633             Person::players[1]->weaponids[0] = 0;
2634
2635         }
2636         break;
2637         case 48:
2638             canattack = 0;
2639             cananger = 0;
2640             Person::players[1]->aitype = passivetype;
2641
2642             tutorialmaxtime = 15;
2643
2644             weapons[0].owner = 1;
2645             weapons[1].owner = 0;
2646             Person::players[0]->weaponactive = 0;
2647             Person::players[0]->num_weapons = 1;
2648             Person::players[0]->weaponids[0] = 1;
2649             Person::players[1]->weaponactive = 0;
2650             Person::players[1]->num_weapons = 1;
2651             Person::players[1]->weaponids[0] = 0;
2652
2653             if (Person::players[0]->weaponactive != -1)
2654                 weapons[Person::players[0]->weaponids[Person::players[0]->weaponactive]].setType(staff);
2655             else
2656                 weapons[0].setType(staff);
2657             break;
2658         case 49:
2659             canattack = 0;
2660             cananger = 0;
2661             Person::players[1]->aitype = passivetype;
2662
2663             tutorialmaxtime = 200;
2664
2665             weapons[1].position = 1000;
2666             weapons[1].tippoint = 1000;
2667
2668             weapons[0].setType(knife);
2669
2670             weapons[0].owner = 0;
2671             Person::players[1]->weaponactive = -1;
2672             Person::players[1]->num_weapons = 0;
2673             Person::players[0]->weaponactive = 0;
2674             Person::players[0]->num_weapons = 1;
2675             Person::players[0]->weaponids[0] = 0;
2676
2677             break;
2678         case 50: {
2679             tutorialmaxtime = 8;
2680
2681             XYZ temp, temp2;
2682             emit_sound_at(fireendsound, Person::players[1]->coords);
2683
2684             for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
2685                 if (Random() % 2 == 0) {
2686                     if (!Person::players[1]->skeleton.free)
2687                         temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
2688                     if (Person::players[1]->skeleton.free)
2689                         temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
2690                     if (!Person::players[1]->skeleton.free)
2691                         temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
2692                     if (Person::players[1]->skeleton.free)
2693                         temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
2694                     Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
2695                 }
2696             }
2697
2698             Person::players[1]->num_weapons = 0;
2699             Person::players[1]->weaponstuck = -1;
2700             Person::players[1]->weaponactive = -1;
2701
2702             weapons.clear();
2703         }
2704         break;
2705         case 51:
2706             tutorialmaxtime = 80000;
2707             break;
2708         default:
2709             break;
2710         }
2711         if (tutorialstage <= 51)
2712             tutorialstagetime = 0;
2713     }
2714
2715     //Tutorial success
2716     if (tutorialstagetime < tutorialmaxtime - 3) {
2717         switch (tutorialstage) {
2718         case 3:
2719             if (deltah || deltav)
2720                 tutorialsuccess += multiplier;
2721             break;
2722         case 4:
2723             if (Person::players[0]->forwardkeydown || Person::players[0]->backkeydown || Person::players[0]->leftkeydown || Person::players[0]->rightkeydown)
2724                 tutorialsuccess += multiplier;
2725             break;
2726         case 5:
2727             if (Person::players[0]->jumpkeydown)
2728                 tutorialsuccess = 1;
2729             break;
2730         case 6:
2731             if (Person::players[0]->isCrouch())
2732                 tutorialsuccess = 1;
2733             break;
2734         case 7:
2735             if (Person::players[0]->animTarget == rollanim)
2736                 tutorialsuccess = 1;
2737             break;
2738         case 8:
2739             if (Person::players[0]->animTarget == sneakanim)
2740                 tutorialsuccess += multiplier;
2741             break;
2742         case 9:
2743             if (Person::players[0]->animTarget == rabbitrunninganim || Person::players[0]->animTarget == wolfrunninganim)
2744                 tutorialsuccess += multiplier;
2745             break;
2746         case 11:
2747             if (Person::players[0]->isWallJump())
2748                 tutorialsuccess = 1;
2749             break;
2750         case 12:
2751             if (Person::players[0]->animTarget == flipanim)
2752                 tutorialsuccess = 1;
2753             break;
2754         case 15:
2755             if (Person::players[0]->animTarget == upunchanim || Person::players[0]->animTarget == winduppunchanim)
2756                 tutorialsuccess = 1;
2757             break;
2758         case 16:
2759             if (Person::players[0]->animTarget == winduppunchanim)
2760                 tutorialsuccess = 1;
2761             break;
2762         case 17:
2763             if (Person::players[0]->animTarget == spinkickanim)
2764                 tutorialsuccess = 1;
2765             break;
2766         case 18:
2767             if (Person::players[0]->animTarget == sweepanim)
2768                 tutorialsuccess = 1;
2769             break;
2770         case 19:
2771             if (Person::players[0]->animTarget == dropkickanim)
2772                 tutorialsuccess = 1;
2773             break;
2774         case 20:
2775             if (Person::players[0]->animTarget == rabbitkickanim)
2776                 tutorialsuccess = 1;
2777             break;
2778         case 21:
2779             if (bonus == cannon)
2780                 tutorialsuccess = 1;
2781             break;
2782         case 22:
2783             if (bonus == spinecrusher)
2784                 tutorialsuccess = 1;
2785             break;
2786         case 23:
2787             if (Person::players[0]->animTarget == walljumprightkickanim || Person::players[0]->animTarget == walljumpleftkickanim)
2788                 tutorialsuccess = 1;
2789             break;
2790         case 24:
2791             if (Person::players[0]->animTarget == rabbittacklinganim)
2792                 tutorialsuccess = 1;
2793             break;
2794         case 25:
2795             if (Person::players[0]->animTarget == backhandspringanim)
2796                 tutorialsuccess = 1;
2797             break;
2798         case 28:
2799             if (animation[Person::players[0]->animTarget].attack == reversed && Person::players[0]->feint)
2800                 tutorialsuccess = 1;
2801             break;
2802         case 29:
2803             if (Person::players[0]->escapednum == 2) {
2804                 tutorialsuccess = 1;
2805                 reversaltrain = 0;
2806                 cananger = 0;
2807                 Person::players[1]->aitype = passivetype;
2808             }
2809             break;
2810         case 33:
2811             if (animation[Person::players[0]->animTarget].attack == reversal)
2812                 tutorialsuccess = 1;
2813             break;
2814         case 34:
2815             if (animation[Person::players[0]->animTarget].attack == reversal)
2816                 tutorialsuccess = 1;
2817             break;
2818         case 35:
2819             if (animation[Person::players[0]->animTarget].attack == reversal) {
2820                 tutorialsuccess = 1;
2821                 reversaltrain = 0;
2822                 cananger = 0;
2823                 Person::players[1]->aitype = passivetype;
2824             }
2825             break;
2826         case 40:
2827             if (Person::players[0]->num_weapons > 0)
2828                 tutorialsuccess = 1;
2829             break;
2830         case 41:
2831             if (Person::players[0]->weaponactive == -1 && Person::players[0]->num_weapons > 0)
2832                 tutorialsuccess = 1;
2833             break;
2834         case 43:
2835             if (Person::players[0]->animTarget == knifeslashstartanim)
2836                 tutorialsuccess = 1;
2837             break;
2838         case 44:
2839             if (animation[Person::players[0]->animTarget].attack == reversal)
2840                 tutorialsuccess = 1;
2841             break;
2842         case 45:
2843             if (animation[Person::players[0]->animTarget].attack == reversal)
2844                 tutorialsuccess = 1;
2845             break;
2846         case 46:
2847             if (animation[Person::players[0]->animTarget].attack == reversal)
2848                 tutorialsuccess = 1;
2849             break;
2850         case 49:
2851             if (Person::players[1]->weaponstuck != -1)
2852                 tutorialsuccess = 1;
2853             break;
2854         default:
2855             break;
2856         }
2857         if (tutorialsuccess >= 1)
2858             tutorialstagetime = tutorialmaxtime - 3;
2859
2860
2861         if (tutorialstagetime == tutorialmaxtime - 3) {
2862             emit_sound_np(consolesuccesssound);
2863         }
2864
2865         if (tutorialsuccess >= 1) {
2866             if (tutorialstage == 34 || tutorialstage == 35)
2867                 tutorialstagetime = tutorialmaxtime - 1;
2868         }
2869     }
2870
2871     if (tutorialstage < 14 || tutorialstage >= 50) {
2872         Person::players[1]->coords.y = 300;
2873         Person::players[1]->velocity = 0;
2874     }
2875 }
2876
2877 void doDebugKeys()
2878 {
2879     float headprop, bodyprop, armprop, legprop;
2880     if (debugmode) {
2881         if (Input::isKeyPressed(SDLK_h)) {
2882             Person::players[0]->damagetolerance = 200000;
2883             Person::players[0]->damage = 0;
2884             Person::players[0]->burnt = 0;
2885             Person::players[0]->permanentdamage = 0;
2886             Person::players[0]->superpermanentdamage = 0;
2887         }
2888
2889         if (Input::isKeyPressed(SDLK_j)) {
2890             environment++;
2891             if (environment > 2)
2892                 environment = 0;
2893             Setenvironment(environment);
2894         }
2895
2896         if (Input::isKeyPressed(SDLK_c)) {
2897             cameramode = 1 - cameramode;
2898         }
2899
2900         if (Input::isKeyPressed(SDLK_x) && !Input::isKeyDown(SDLK_LSHIFT)) {
2901             if (Person::players[0]->num_weapons > 0) {
2902                 if (weapons[Person::players[0]->weaponids[0]].getType() == sword)
2903                     weapons[Person::players[0]->weaponids[0]].setType(staff);
2904                 else if (weapons[Person::players[0]->weaponids[0]].getType() == staff)
2905                     weapons[Person::players[0]->weaponids[0]].setType(knife);
2906                 else
2907                     weapons[Person::players[0]->weaponids[0]].setType(sword);
2908             }
2909         }
2910
2911         if (Input::isKeyPressed(SDLK_x) && Input::isKeyDown(SDLK_LSHIFT)) {
2912             int closest = findClosestPlayer();
2913             if (closest >= 0) {
2914                 if (Person::players[closest]->num_weapons) {
2915                     if (weapons[Person::players[closest]->weaponids[0]].getType() == sword)
2916                         weapons[Person::players[closest]->weaponids[0]].setType(staff);
2917                     else if (weapons[Person::players[closest]->weaponids[0]].getType() == staff)
2918                         weapons[Person::players[closest]->weaponids[0]].setType(knife);
2919                     else
2920                         weapons[Person::players[closest]->weaponids[0]].setType(sword);
2921                 }
2922                 if (!Person::players[closest]->num_weapons) {
2923                     Person::players[closest]->weaponids[0] = weapons.size();
2924
2925                     weapons.push_back(Weapon(knife, closest));
2926
2927                     Person::players[closest]->num_weapons = 1;
2928                 }
2929             }
2930         }
2931
2932         if (Input::isKeyDown(SDLK_u)) {
2933             int closest = findClosestPlayer();
2934             if (closest >= 0) {
2935                 Person::players[closest]->yaw += multiplier * 50;
2936                 Person::players[closest]->targetyaw = Person::players[closest]->yaw;
2937             }
2938         }
2939
2940
2941         if (Input::isKeyPressed(SDLK_o) && !Input::isKeyDown(SDLK_LSHIFT)) {
2942             int closest = findClosestPlayer();
2943             if (Input::isKeyDown(SDLK_LCTRL))
2944                 closest = 0;
2945
2946             if (closest >= 0) {
2947                 Person::players[closest]->whichskin++;
2948                 if (Person::players[closest]->whichskin > 9)
2949                     Person::players[closest]->whichskin = 0;
2950                 if (Person::players[closest]->whichskin > 2 && Person::players[closest]->creature == wolftype)
2951                     Person::players[closest]->whichskin = 0;
2952
2953                 Person::players[closest]->skeleton.drawmodel.textureptr.load(creatureskin[Person::players[closest]->creature][Person::players[closest]->whichskin], 1,
2954                         &Person::players[closest]->skeleton.skinText[0], &Person::players[closest]->skeleton.skinsize);
2955             }
2956
2957             if (Person::players[closest]->numclothes) {
2958                 for (int i = 0; i < Person::players[closest]->numclothes; i++) {
2959                     tintr = Person::players[closest]->clothestintr[i];
2960                     tintg = Person::players[closest]->clothestintg[i];
2961                     tintb = Person::players[closest]->clothestintb[i];
2962                     AddClothes((char *)Person::players[closest]->clothes[i], &Person::players[closest]->skeleton.skinText[0]);
2963                 }
2964                 Person::players[closest]->DoMipmaps();
2965             }
2966         }
2967
2968         if (Input::isKeyPressed(SDLK_o) && Input::isKeyDown(SDLK_LSHIFT)) {
2969             int closest = findClosestPlayer();
2970             if (closest >= 0) {
2971                 if (Person::players[closest]->creature == wolftype) {
2972                     headprop = Person::players[closest]->proportionhead.x / 1.1;
2973                     bodyprop = Person::players[closest]->proportionbody.x / 1.1;
2974                     armprop = Person::players[closest]->proportionarms.x / 1.1;
2975                     legprop = Person::players[closest]->proportionlegs.x / 1.1;
2976                 }
2977
2978                 if (Person::players[closest]->creature == rabbittype) {
2979                     headprop = Person::players[closest]->proportionhead.x / 1.2;
2980                     bodyprop = Person::players[closest]->proportionbody.x / 1.05;
2981                     armprop = Person::players[closest]->proportionarms.x / 1.00;
2982                     legprop = Person::players[closest]->proportionlegs.x / 1.1;
2983                 }
2984
2985
2986                 if (Person::players[closest]->creature == rabbittype) {
2987                     Person::players[closest]->skeleton.id = closest;
2988                     Person::players[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);
2989                     Person::players[closest]->skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &Person::players[closest]->skeleton.skinText[closest], &Person::players[closest]->skeleton.skinsize);
2990                     Person::players[closest]->whichskin = 0;
2991                     Person::players[closest]->creature = wolftype;
2992
2993                     Person::players[closest]->proportionhead = 1.1;
2994                     Person::players[closest]->proportionbody = 1.1;
2995                     Person::players[closest]->proportionarms = 1.1;
2996                     Person::players[closest]->proportionlegs = 1.1;
2997                     Person::players[closest]->proportionlegs.y = 1.1;
2998                     Person::players[closest]->scale = .23 * 5 * Person::players[0]->scale;
2999
3000                     Person::players[closest]->damagetolerance = 300;
3001                 } else {
3002                     Person::players[closest]->skeleton.id = closest;
3003                     Person::players[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);
3004                     Person::players[closest]->skeleton.drawmodel.textureptr.load(":Data:Textures:Fur3.jpg", 1, &Person::players[closest]->skeleton.skinText[0], &Person::players[closest]->skeleton.skinsize);
3005                     Person::players[closest]->whichskin = 0;
3006                     Person::players[closest]->creature = rabbittype;
3007
3008                     Person::players[closest]->proportionhead = 1.2;
3009                     Person::players[closest]->proportionbody = 1.05;
3010                     Person::players[closest]->proportionarms = 1.00;
3011                     Person::players[closest]->proportionlegs = 1.1;
3012                     Person::players[closest]->proportionlegs.y = 1.05;
3013                     Person::players[closest]->scale = .2 * 5 * Person::players[0]->scale;
3014
3015                     Person::players[closest]->damagetolerance = 200;
3016                 }
3017
3018                 if (Person::players[closest]->creature == wolftype) {
3019                     Person::players[closest]->proportionhead = 1.1 * headprop;
3020                     Person::players[closest]->proportionbody = 1.1 * bodyprop;
3021                     Person::players[closest]->proportionarms = 1.1 * armprop;
3022                     Person::players[closest]->proportionlegs = 1.1 * legprop;
3023                 }
3024
3025                 if (Person::players[closest]->creature == rabbittype) {
3026                     Person::players[closest]->proportionhead = 1.2 * headprop;
3027                     Person::players[closest]->proportionbody = 1.05 * bodyprop;
3028                     Person::players[closest]->proportionarms = 1.00 * armprop;
3029                     Person::players[closest]->proportionlegs = 1.1 * legprop;
3030                     Person::players[closest]->proportionlegs.y = 1.05 * legprop;
3031                 }
3032
3033             }
3034         }
3035
3036         if (Input::isKeyPressed(SDLK_b) && !Input::isKeyDown(SDLK_LSHIFT)) {
3037             slomo = 1 - slomo;
3038             slomodelay = 1000;
3039         }
3040
3041
3042         if (((Input::isKeyPressed(SDLK_i) && !Input::isKeyDown(SDLK_LSHIFT)))) {
3043             int closest = -1;
3044             float closestdist = std::numeric_limits<float>::max();
3045
3046             for (int i = 1; i < numplayers; i++) {
3047                 float distance = distsq(&Person::players[i]->coords, &Person::players[0]->coords);
3048                 if (!Person::players[i]->headless)
3049                     if (distance < closestdist) {
3050                         closestdist = distance;
3051                         closest = i;
3052                     }
3053             }
3054
3055             XYZ flatfacing2, flatvelocity2;
3056             XYZ blah;
3057             if (closest != -1 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
3058                 blah = Person::players[closest]->coords;
3059                 XYZ headspurtdirection;
3060                 //int i = Person::players[closest]->skeleton.jointlabels[head];
3061                 Joint& headjoint = Person::players[closest]->joint(head);
3062                 for (int k = 0; k < Person::players[closest]->skeleton.num_joints; k++) {
3063                     if (!Person::players[closest]->skeleton.free)
3064                         flatvelocity2 = Person::players[closest]->velocity;
3065                     if (Person::players[closest]->skeleton.free)
3066                         flatvelocity2 = headjoint.velocity;
3067                     if (!Person::players[closest]->skeleton.free)
3068                         flatfacing2 = DoRotation(DoRotation(DoRotation(headjoint.position, 0, 0, Person::players[closest]->tilt), Person::players[closest]->tilt2, 0, 0), 0, Person::players[closest]->yaw, 0) * Person::players[closest]->scale + Person::players[closest]->coords;
3069                     if (Person::players[closest]->skeleton.free)
3070                         flatfacing2 = headjoint.position * Person::players[closest]->scale + Person::players[closest]->coords;
3071                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3072                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3073                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3074                     headspurtdirection = headjoint.position - Person::players[closest]->jointPos(neck);
3075                     Normalise(&headspurtdirection);
3076                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, .6, 1);
3077                     flatvelocity2 += headspurtdirection * 8;
3078                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 / 2, 1, 1, 1, .16, 1);
3079                 }
3080                 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
3081
3082                 emit_sound_at(splattersound, blah);
3083                 emit_sound_at(breaksound2, blah, 100.);
3084
3085                 if (Person::players[closest]->skeleton.free == 2)
3086                     Person::players[closest]->skeleton.free = 0;
3087                 Person::players[closest]->RagDoll(0);
3088                 Person::players[closest]->dead = 2;
3089                 Person::players[closest]->headless = 1;
3090                 Person::players[closest]->DoBloodBig(3, 165);
3091
3092                 camerashake += .3;
3093             }
3094         }
3095
3096         if (((Input::isKeyPressed(SDLK_i) && Input::isKeyDown(SDLK_LSHIFT)))) {
3097             int closest = findClosestPlayer();
3098             XYZ flatfacing2, flatvelocity2;
3099             XYZ blah;
3100             if (closest >= 0 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
3101                 blah = Person::players[closest]->coords;
3102                 emit_sound_at(splattersound, blah);
3103                 emit_sound_at(breaksound2, blah);
3104
3105                 for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
3106                     if (!Person::players[closest]->skeleton.free)
3107                         flatvelocity2 = Person::players[closest]->velocity;
3108                     if (Person::players[closest]->skeleton.free)
3109                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
3110                     if (!Person::players[closest]->skeleton.free)
3111                         flatfacing2 = DoRotation(DoRotation(DoRotation(Person::players[closest]->skeleton.joints[i].position, 0, 0, Person::players[closest]->tilt), Person::players[closest]->tilt2, 0, 0), 0, Person::players[closest]->yaw, 0) * Person::players[closest]->scale + Person::players[closest]->coords;
3112                     if (Person::players[closest]->skeleton.free)
3113                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
3114                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3115                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3116                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3117                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
3118                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .3, 1);
3119                     Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
3120                 }
3121
3122                 for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
3123                     if (!Person::players[closest]->skeleton.free)
3124                         flatvelocity2 = Person::players[closest]->velocity;
3125                     if (Person::players[closest]->skeleton.free)
3126                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
3127                     if (!Person::players[closest]->skeleton.free)
3128                         flatfacing2 = DoRotation(DoRotation(DoRotation(Person::players[closest]->skeleton.joints[i].position, 0, 0, Person::players[closest]->tilt), Person::players[closest]->tilt2, 0, 0), 0, Person::players[closest]->yaw, 0) * Person::players[closest]->scale + Person::players[closest]->coords;
3129                     if (Person::players[closest]->skeleton.free)
3130                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
3131                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3132                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3133                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3134                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
3135                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
3136                 }
3137
3138                 for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
3139                     if (!Person::players[closest]->skeleton.free)
3140                         flatvelocity2 = Person::players[closest]->velocity;
3141                     if (Person::players[closest]->skeleton.free)
3142                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
3143                     if (!Person::players[closest]->skeleton.free)
3144                         flatfacing2 = DoRotation(DoRotation(DoRotation(Person::players[closest]->skeleton.joints[i].position, 0, 0, Person::players[closest]->tilt), Person::players[closest]->tilt2, 0, 0), 0, Person::players[closest]->yaw, 0) * Person::players[closest]->scale + Person::players[closest]->coords;
3145                     if (Person::players[closest]->skeleton.free)
3146                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
3147                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3148                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3149                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3150                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
3151                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
3152                 }
3153
3154                 for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
3155                     if (!Person::players[closest]->skeleton.free)
3156                         flatvelocity2 = Person::players[closest]->velocity;
3157                     if (Person::players[closest]->skeleton.free)
3158                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
3159                     if (!Person::players[closest]->skeleton.free)
3160                         flatfacing2 = DoRotation(DoRotation(DoRotation(Person::players[closest]->skeleton.joints[i].position, 0, 0, Person::players[closest]->tilt), Person::players[closest]->tilt2, 0, 0), 0, Person::players[closest]->yaw, 0) * Person::players[closest]->scale + Person::players[closest]->coords;
3161                     if (Person::players[closest]->skeleton.free)
3162                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
3163                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3164                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3165                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3166                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
3167                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
3168                 }
3169
3170                 XYZ temppos;
3171                 for (int j = 0; j < numplayers; j++) {
3172                     if (j != closest) {
3173                         if (distsq(&Person::players[j]->coords, &Person::players[closest]->coords) < 25) {
3174                             Person::players[j]->DoDamage((25 - distsq(&Person::players[j]->coords, &Person::players[closest]->coords)) * 60);
3175                             if (Person::players[j]->skeleton.free == 2)
3176                                 Person::players[j]->skeleton.free = 1;
3177                             Person::players[j]->skeleton.longdead = 0;
3178                             Person::players[j]->RagDoll(0);
3179                             for (int i = 0; i < Person::players[j]->skeleton.num_joints; i++) {
3180                                 temppos = Person::players[j]->skeleton.joints[i].position + Person::players[j]->coords;
3181                                 if (distsq(&temppos, &Person::players[closest]->coords) < 25) {
3182                                     flatvelocity2 = temppos - Person::players[closest]->coords;
3183                                     Normalise(&flatvelocity2);
3184                                     Person::players[j]->skeleton.joints[i].velocity += flatvelocity2 * ((20 - distsq(&temppos, &Person::players[closest]->coords)) * 20);
3185                                 }
3186                             }
3187                         }
3188                     }
3189                 }
3190
3191                 Person::players[closest]->DoDamage(10000);
3192                 Person::players[closest]->RagDoll(0);
3193                 Person::players[closest]->dead = 2;
3194                 Person::players[closest]->coords = 20;
3195                 Person::players[closest]->skeleton.free = 2;
3196
3197                 camerashake += .6;
3198
3199             }
3200         }
3201
3202         if (Input::isKeyPressed(SDLK_f)) {
3203             Person::players[0]->onfire = 1 - Person::players[0]->onfire;
3204             if (Person::players[0]->onfire) {
3205                 Person::players[0]->CatchFire();
3206             }
3207             if (!Person::players[0]->onfire) {
3208                 emit_sound_at(fireendsound, Person::players[0]->coords);
3209                 pause_sound(stream_firesound);
3210             }
3211         }
3212
3213         if (Input::isKeyPressed(SDLK_n) && !Input::isKeyDown(SDLK_LCTRL)) {
3214             //if(!Person::players[0]->skeleton.free)Person::players[0]->damage+=500;
3215             Person::players[0]->RagDoll(0);
3216             //Person::players[0]->spurt=1;
3217             //Person::players[0]->DoDamage(1000);
3218
3219             emit_sound_at(whooshsound, Person::players[0]->coords, 128.);
3220         }
3221
3222         if (Input::isKeyPressed(SDLK_n) && Input::isKeyDown(SDLK_LCTRL)) {
3223             for (int i = 0; i < objects.numobjects; i++) {
3224                 if (objects.type[i] == treeleavestype) {
3225                     objects.scale[i] *= .9;
3226                 }
3227             }
3228         }
3229
3230         if (Input::isKeyPressed(SDLK_m) && Input::isKeyDown(SDLK_LSHIFT)) {
3231             editorenabled = 1 - editorenabled;
3232             if (editorenabled) {
3233                 Person::players[0]->damagetolerance = 100000;
3234             } else {
3235                 Person::players[0]->damagetolerance = 200;
3236             }
3237             Person::players[0]->damage = 0; // these lines were in both if and else, but I think they would better fit in the if
3238             Person::players[0]->permanentdamage = 0;
3239             Person::players[0]->superpermanentdamage = 0;
3240             Person::players[0]->bloodloss = 0;
3241             Person::players[0]->deathbleeding = 0;
3242         }
3243
3244         //skip level
3245         if (whichlevel != -2 && Input::isKeyPressed(SDLK_k) && Input::isKeyDown(SDLK_LSHIFT) && !editorenabled) {
3246             targetlevel++;
3247             if (targetlevel > numchallengelevels - 1)
3248                 targetlevel = 0;
3249             loading = 1;
3250             leveltime = 5;
3251         }
3252
3253         if (editorenabled) {
3254             if (Input::isKeyPressed(SDLK_DELETE) && Input::isKeyDown(SDLK_LSHIFT)) {
3255                 int closest = findClosestPlayer();
3256                 if (closest >= 0) {
3257                     //player[closest]=player[numplayers-1];
3258                     //Person::players[closest]->skeleton=Person::players[numplayers-1]->skeleton;
3259                     numplayers--;
3260                 }
3261             }
3262
3263             if (Input::isKeyPressed(SDLK_DELETE) && Input::isKeyDown(SDLK_LCTRL)) {
3264                 int closest = findClosestObject();
3265                 if (closest >= 0)
3266                     objects.position[closest].y -= 500;
3267             }
3268
3269             if (Input::isKeyPressed(SDLK_m) && Input::isKeyDown(SDLK_LSHIFT)) {
3270                 //drawmode++;
3271                 //if(drawmode>2)drawmode=0;
3272                 if (objects.numobjects < max_objects - 1) {
3273                     XYZ boxcoords;
3274                     boxcoords.x = Person::players[0]->coords.x;
3275                     boxcoords.z = Person::players[0]->coords.z;
3276                     boxcoords.y = Person::players[0]->coords.y - 3;
3277                     if (editortype == bushtype)
3278                         boxcoords.y = Person::players[0]->coords.y - .5;
3279                     if (editortype == firetype)
3280                         boxcoords.y = Person::players[0]->coords.y - .5;
3281                     //objects.MakeObject(abs(Random()%3),boxcoords,Random()%360);
3282                     float temprotat, temprotat2;
3283                     temprotat = editoryaw;
3284                     temprotat2 = editorpitch;
3285                     if (temprotat < 0 || editortype == bushtype)
3286                         temprotat = Random() % 360;
3287                     if (temprotat2 < 0)
3288                         temprotat2 = Random() % 360;
3289
3290                     objects.MakeObject(editortype, boxcoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
3291                     if (editortype == treetrunktype)
3292                         objects.MakeObject(treeleavestype, boxcoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
3293                 }
3294             }
3295
3296             if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3297                 if (numplayers < maxplayers - 1) {
3298                     Person::players[numplayers]->scale = .2 * 5 * Person::players[0]->scale;
3299                     Person::players[numplayers]->creature = rabbittype;
3300                     Person::players[numplayers]->howactive = editoractive;
3301                     Person::players[numplayers]->skeleton.id = numplayers;
3302                     Person::players[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);
3303
3304                     //texsize=512*512*3/texdetail/texdetail;
3305                     //if(!Person::players[numplayers]->loaded)Person::players[numplayers]->skeleton.skinText = new GLubyte[texsize];
3306                     //Person::players[numplayers]->skeleton.skinText.resize(texsize);
3307
3308                     int k = abs(Random() % 2) + 1;
3309                     if (k == 0) {
3310                         Person::players[numplayers]->skeleton.drawmodel.textureptr.load(":Data:Textures:Fur3.jpg", 1, &Person::players[numplayers]->skeleton.skinText[0], &Person::players[numplayers]->skeleton.skinsize);
3311                         Person::players[numplayers]->whichskin = 0;
3312                     } else if (k == 1) {
3313                         Person::players[numplayers]->skeleton.drawmodel.textureptr.load(":Data:Textures:Fur.jpg", 1, &Person::players[numplayers]->skeleton.skinText[0], &Person::players[numplayers]->skeleton.skinsize);
3314                         Person::players[numplayers]->whichskin = 1;
3315                     } else {
3316                         Person::players[numplayers]->skeleton.drawmodel.textureptr.load(":Data:Textures:Fur2.jpg", 1, &Person::players[numplayers]->skeleton.skinText[0], &Person::players[numplayers]->skeleton.skinsize);
3317                         Person::players[numplayers]->whichskin = 2;
3318                     }
3319
3320                     Person::players[numplayers]->skeleton.drawmodelclothes.textureptr.load(":Data:Textures:Belt.png", 1, 1);
3321                     Person::players[numplayers]->power = 1;
3322                     Person::players[numplayers]->speedmult = 1;
3323                     Person::players[numplayers]->animCurrent = bounceidleanim;
3324                     Person::players[numplayers]->animTarget = bounceidleanim;
3325                     Person::players[numplayers]->frameCurrent = 0;
3326                     Person::players[numplayers]->frameTarget = 1;
3327                     Person::players[numplayers]->target = 0;
3328                     Person::players[numplayers]->bled = 0;
3329                     Person::players[numplayers]->speed = 1 + (float)(Random() % 100) / 1000;
3330
3331                     Person::players[numplayers]->targetyaw = Person::players[0]->targetyaw;
3332                     Person::players[numplayers]->yaw = Person::players[0]->yaw;
3333
3334                     Person::players[numplayers]->velocity = 0;
3335                     Person::players[numplayers]->coords = Person::players[0]->coords;
3336                     Person::players[numplayers]->oldcoords = Person::players[numplayers]->coords;
3337                     Person::players[numplayers]->realoldcoords = Person::players[numplayers]->coords;
3338
3339                     Person::players[numplayers]->id = numplayers;
3340                     Person::players[numplayers]->skeleton.id = numplayers;
3341                     Person::players[numplayers]->updatedelay = 0;
3342                     Person::players[numplayers]->normalsupdatedelay = 0;
3343
3344                     Person::players[numplayers]->aitype = passivetype;
3345
3346                     if (Person::players[0]->creature == wolftype) {
3347                         headprop = Person::players[0]->proportionhead.x / 1.1;
3348                         bodyprop = Person::players[0]->proportionbody.x / 1.1;
3349                         armprop = Person::players[0]->proportionarms.x / 1.1;
3350                         legprop = Person::players[0]->proportionlegs.x / 1.1;
3351                     }
3352
3353                     if (Person::players[0]->creature == rabbittype) {
3354                         headprop = Person::players[0]->proportionhead.x / 1.2;
3355                         bodyprop = Person::players[0]->proportionbody.x / 1.05;
3356                         armprop = Person::players[0]->proportionarms.x / 1.00;
3357                         legprop = Person::players[0]->proportionlegs.x / 1.1;
3358                     }
3359
3360                     if (Person::players[numplayers]->creature == wolftype) {
3361                         Person::players[numplayers]->proportionhead = 1.1 * headprop;
3362                         Person::players[numplayers]->proportionbody = 1.1 * bodyprop;
3363                         Person::players[numplayers]->proportionarms = 1.1 * armprop;
3364                         Person::players[numplayers]->proportionlegs = 1.1 * legprop;
3365                     }
3366
3367                     if (Person::players[numplayers]->creature == rabbittype) {
3368                         Person::players[numplayers]->proportionhead = 1.2 * headprop;
3369                         Person::players[numplayers]->proportionbody = 1.05 * bodyprop;
3370                         Person::players[numplayers]->proportionarms = 1.00 * armprop;
3371                         Person::players[numplayers]->proportionlegs = 1.1 * legprop;
3372                         Person::players[numplayers]->proportionlegs.y = 1.05 * legprop;
3373                     }
3374
3375                     Person::players[numplayers]->headless = 0;
3376                     Person::players[numplayers]->onfire = 0;
3377
3378                     if (cellophane) {
3379                         Person::players[numplayers]->proportionhead.z = 0;
3380                         Person::players[numplayers]->proportionbody.z = 0;
3381                         Person::players[numplayers]->proportionarms.z = 0;
3382                         Person::players[numplayers]->proportionlegs.z = 0;
3383                     }
3384
3385                     Person::players[numplayers]->tempanimation.Load((char *)"Tempanim", 0, 0);
3386
3387                     Person::players[numplayers]->damagetolerance = 200;
3388
3389                     Person::players[numplayers]->protectionhead = Person::players[0]->protectionhead;
3390                     Person::players[numplayers]->protectionhigh = Person::players[0]->protectionhigh;
3391                     Person::players[numplayers]->protectionlow = Person::players[0]->protectionlow;
3392                     Person::players[numplayers]->armorhead = Person::players[0]->armorhead;
3393                     Person::players[numplayers]->armorhigh = Person::players[0]->armorhigh;
3394                     Person::players[numplayers]->armorlow = Person::players[0]->armorlow;
3395                     Person::players[numplayers]->metalhead = Person::players[0]->metalhead;
3396                     Person::players[numplayers]->metalhigh = Person::players[0]->metalhigh;
3397                     Person::players[numplayers]->metallow = Person::players[0]->metallow;
3398
3399                     Person::players[numplayers]->immobile = Person::players[0]->immobile;
3400
3401                     Person::players[numplayers]->numclothes = Person::players[0]->numclothes;
3402                     if (Person::players[numplayers]->numclothes)
3403                         for (int i = 0; i < Person::players[numplayers]->numclothes; i++) {
3404                             strcpy(Person::players[numplayers]->clothes[i], Person::players[0]->clothes[i]);
3405                             Person::players[numplayers]->clothestintr[i] = Person::players[0]->clothestintr[i];
3406                             Person::players[numplayers]->clothestintg[i] = Person::players[0]->clothestintg[i];
3407                             Person::players[numplayers]->clothestintb[i] = Person::players[0]->clothestintb[i];
3408                             tintr = Person::players[numplayers]->clothestintr[i];
3409                             tintg = Person::players[numplayers]->clothestintg[i];
3410                             tintb = Person::players[numplayers]->clothestintb[i];
3411                             AddClothes((char *)Person::players[numplayers]->clothes[i], &Person::players[numplayers]->skeleton.skinText[0]);
3412                         }
3413                     if (Person::players[numplayers]->numclothes) {
3414                         Person::players[numplayers]->DoMipmaps();
3415                     }
3416
3417                     Person::players[numplayers]->power = Person::players[0]->power;
3418                     Person::players[numplayers]->speedmult = Person::players[0]->speedmult;
3419
3420                     Person::players[numplayers]->damage = 0;
3421                     Person::players[numplayers]->permanentdamage = 0;
3422                     Person::players[numplayers]->superpermanentdamage = 0;
3423                     Person::players[numplayers]->deathbleeding = 0;
3424                     Person::players[numplayers]->bleeding = 0;
3425                     Person::players[numplayers]->numwaypoints = 0;
3426                     Person::players[numplayers]->waypoint = 0;
3427                     Person::players[numplayers]->jumppath = 0;
3428                     Person::players[numplayers]->weaponstuck = -1;
3429                     Person::players[numplayers]->weaponactive = -1;
3430                     Person::players[numplayers]->num_weapons = 0;
3431                     Person::players[numplayers]->bloodloss = 0;
3432                     Person::players[numplayers]->dead = 0;
3433
3434                     Person::players[numplayers]->loaded = 1;
3435
3436                     numplayers++;
3437                 }
3438             }
3439
3440             if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LSHIFT)) {
3441                 if (Person::players[numplayers - 1]->numwaypoints < 90) {
3442                     Person::players[numplayers - 1]->waypoints[Person::players[numplayers - 1]->numwaypoints] = Person::players[0]->coords;
3443                     Person::players[numplayers - 1]->waypointtype[Person::players[numplayers - 1]->numwaypoints] = editorpathtype;
3444                     Person::players[numplayers - 1]->numwaypoints++;
3445                 }
3446             }
3447
3448             if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LCTRL)) {
3449                 if (numpathpoints < 30) {
3450                     bool connected, alreadyconnected;
3451                     connected = 0;
3452                     if (numpathpoints > 1)
3453                         for (int i = 0; i < numpathpoints; i++) {
3454                             if (distsq(&pathpoint[i], &Person::players[0]->coords) < .5 && i != pathpointselected && !connected) {
3455                                 alreadyconnected = 0;
3456                                 for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
3457                                     if (pathpointconnect[pathpointselected][j] == i)
3458                                         alreadyconnected = 1;
3459                                 }
3460                                 if (!alreadyconnected) {
3461                                     numpathpointconnect[pathpointselected]++;
3462                                     connected = 1;
3463                                     pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
3464                                 }
3465                             }
3466                         }
3467                     if (!connected) {
3468                         numpathpoints++;
3469                         pathpoint[numpathpoints - 1] = Person::players[0]->coords;
3470                         numpathpointconnect[numpathpoints - 1] = 0;
3471                         if (numpathpoints > 1 && pathpointselected != -1) {
3472                             numpathpointconnect[pathpointselected]++;
3473                             pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
3474                         }
3475                         pathpointselected = numpathpoints - 1;
3476                     }
3477                 }
3478             }
3479
3480             if (Input::isKeyPressed(SDLK_PERIOD)) {
3481                 pathpointselected++;
3482                 if (pathpointselected >= numpathpoints)
3483                     pathpointselected = -1;
3484             }
3485             if (Input::isKeyPressed(SDLK_COMMA) && !Input::isKeyDown(SDLK_LSHIFT)) {
3486                 pathpointselected--;
3487                 if (pathpointselected <= -2)
3488                     pathpointselected = numpathpoints - 1;
3489             }
3490             if (Input::isKeyPressed(SDLK_COMMA) && Input::isKeyDown(SDLK_LSHIFT)) {
3491                 if (pathpointselected != -1) {
3492                     numpathpoints--;
3493                     pathpoint[pathpointselected] = pathpoint[numpathpoints];
3494                     numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
3495                     for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
3496                         pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
3497                     }
3498                     for (int i = 0; i < numpathpoints; i++) {
3499                         for (int j = 0; j < numpathpointconnect[i]; j++) {
3500                             if (pathpointconnect[i][j] == pathpointselected) {
3501                                 pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
3502                                 numpathpointconnect[i]--;
3503                             }
3504                             if (pathpointconnect[i][j] == numpathpoints) {
3505                                 pathpointconnect[i][j] = pathpointselected;
3506                             }
3507                         }
3508                     }
3509                     pathpointselected = numpathpoints - 1;
3510                 }
3511             }
3512
3513             if (Input::isKeyPressed(SDLK_LEFT) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3514                 editortype--;
3515                 if (editortype == treeleavestype || editortype == 10)
3516                     editortype--;
3517                 if (editortype < 0)
3518                     editortype = firetype;
3519             }
3520
3521             if (Input::isKeyPressed(SDLK_RIGHT) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3522                 editortype++;
3523                 if (editortype == treeleavestype || editortype == 10)
3524                     editortype++;
3525                 if (editortype > firetype)
3526                     editortype = 0;
3527             }
3528
3529             if (Input::isKeyDown(SDLK_LEFT) && !Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3530                 editoryaw -= multiplier * 100;
3531                 if (editoryaw < -.01)
3532                     editoryaw = -.01;
3533             }
3534
3535             if (Input::isKeyDown(SDLK_RIGHT) && !Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3536                 editoryaw += multiplier * 100;
3537             }
3538
3539             if (Input::isKeyDown(SDLK_UP) && !Input::isKeyDown(SDLK_LCTRL)) {
3540                 editorsize += multiplier;
3541             }
3542
3543             if (Input::isKeyDown(SDLK_DOWN) && !Input::isKeyDown(SDLK_LCTRL)) {
3544                 editorsize -= multiplier;
3545                 if (editorsize < .1)
3546                     editorsize = .1;
3547             }
3548
3549
3550             if (Input::isKeyPressed(SDLK_LEFT) && Input::isKeyDown(SDLK_LSHIFT) && Input::isKeyDown(SDLK_LCTRL)) {
3551                 mapradius -= multiplier * 10;
3552             }
3553
3554             if (Input::isKeyPressed(SDLK_RIGHT) && Input::isKeyDown(SDLK_LSHIFT) && Input::isKeyDown(SDLK_LCTRL)) {
3555                 mapradius += multiplier * 10;
3556             }
3557             if (Input::isKeyDown(SDLK_UP) && Input::isKeyDown(SDLK_LCTRL)) {
3558                 editorpitch += multiplier * 100;
3559             }
3560
3561             if (Input::isKeyDown(SDLK_DOWN) && Input::isKeyDown(SDLK_LCTRL)) {
3562                 editorpitch -= multiplier * 100;
3563                 if (editorpitch < -.01)
3564                     editorpitch = -.01;
3565             }
3566             if (Input::isKeyPressed(SDLK_DELETE) && objects.numobjects && Input::isKeyDown(SDLK_LSHIFT)) {
3567                 int closest = findClosestObject();
3568                 if (closest >= 0)
3569                     objects.DeleteObject(closest);
3570             }
3571         }
3572     }
3573 }
3574
3575 void doJumpReversals()
3576 {
3577     for (int k = 0; k < numplayers; k++)
3578         for (int i = k; i < numplayers; i++) {
3579             if (i == k)
3580                 continue;
3581             if (     Person::players[k]->skeleton.free == 0 &&
3582                      Person::players[i]->skeleton.oldfree == 0 &&
3583                      (Person::players[i]->animTarget == jumpupanim ||
3584                       Person::players[k]->animTarget == jumpupanim) &&
3585                      (Person::players[i]->aitype == playercontrolled ||
3586                       Person::players[k]->aitype == playercontrolled) &&
3587                      (Person::players[i]->aitype == attacktypecutoff && Person::players[i]->stunned <= 0 ||
3588                       Person::players[k]->aitype == attacktypecutoff && Person::players[k]->stunned <= 0)) {
3589                 if (     distsq(&Person::players[i]->coords, &Person::players[k]->coords) < 10 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5) &&
3590                          distsqflat(&Person::players[i]->coords, &Person::players[k]->coords) < 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
3591                     //TODO: refactor two huge similar ifs
3592                     if (Person::players[i]->animTarget == jumpupanim &&
3593                             Person::players[k]->animTarget != getupfrombackanim &&
3594                             Person::players[k]->animTarget != getupfromfrontanim &&
3595                             animation[Person::players[k]->animTarget].height == middleheight &&
3596                             normaldotproduct(Person::players[i]->velocity, Person::players[k]->coords - Person::players[i]->coords) < 0 &&
3597                             (Person::players[k]->aitype == playercontrolled && Person::players[k]->attackkeydown ||
3598                              Person::players[k]->aitype != playercontrolled)) {
3599                         Person::players[i]->victim = Person::players[k];
3600                         Person::players[i]->velocity = 0;
3601                         Person::players[i]->animCurrent = jumpreversedanim;
3602                         Person::players[i]->animTarget = jumpreversedanim;
3603                         Person::players[i]->frameCurrent = 0;
3604                         Person::players[i]->frameTarget = 1;
3605                         Person::players[i]->targettilt2 = 0;
3606                         Person::players[k]->victim = Person::players[i];
3607                         Person::players[k]->velocity = 0;
3608                         Person::players[k]->animCurrent = jumpreversalanim;
3609                         Person::players[k]->animTarget = jumpreversalanim;
3610                         Person::players[k]->frameCurrent = 0;
3611                         Person::players[k]->frameTarget = 1;
3612                         Person::players[k]->targettilt2 = 0;
3613                         if (Person::players[i]->coords.y < Person::players[k]->coords.y + 1) {
3614                             Person::players[i]->animCurrent = rabbitkickreversedanim;
3615                             Person::players[i]->animTarget = rabbitkickreversedanim;
3616                             Person::players[i]->frameCurrent = 1;
3617                             Person::players[i]->frameTarget = 2;
3618                             Person::players[k]->animCurrent = rabbitkickreversalanim;
3619                             Person::players[k]->animTarget = rabbitkickreversalanim;
3620                             Person::players[k]->frameCurrent = 1;
3621                             Person::players[k]->frameTarget = 2;
3622                         }
3623                         Person::players[i]->target = 0;
3624                         Person::players[k]->oldcoords = Person::players[k]->coords;
3625                         Person::players[i]->coords = Person::players[k]->coords;
3626                         Person::players[k]->targetyaw = Person::players[i]->targetyaw;
3627                         Person::players[k]->yaw = Person::players[i]->targetyaw;
3628                         if (Person::players[k]->aitype == attacktypecutoff)
3629                             Person::players[k]->stunned = .5;
3630                     }
3631                     if (Person::players[k]->animTarget == jumpupanim &&
3632                             Person::players[i]->animTarget != getupfrombackanim &&
3633                             Person::players[i]->animTarget != getupfromfrontanim &&
3634                             animation[Person::players[i]->animTarget].height == middleheight &&
3635                             normaldotproduct(Person::players[k]->velocity, Person::players[i]->coords - Person::players[k]->coords) < 0 &&
3636                             ((Person::players[i]->aitype == playercontrolled && Person::players[i]->attackkeydown) ||
3637                              Person::players[i]->aitype != playercontrolled)) {
3638                         Person::players[k]->victim = Person::players[i];
3639                         Person::players[k]->velocity = 0;
3640                         Person::players[k]->animCurrent = jumpreversedanim;
3641                         Person::players[k]->animTarget = jumpreversedanim;
3642                         Person::players[k]->frameCurrent = 0;
3643                         Person::players[k]->frameTarget = 1;
3644                         Person::players[k]->targettilt2 = 0;
3645                         Person::players[i]->victim = Person::players[k];
3646                         Person::players[i]->velocity = 0;
3647                         Person::players[i]->animCurrent = jumpreversalanim;
3648                         Person::players[i]->animTarget = jumpreversalanim;
3649                         Person::players[i]->frameCurrent = 0;
3650                         Person::players[i]->frameTarget = 1;
3651                         Person::players[i]->targettilt2 = 0;
3652                         if (Person::players[k]->coords.y < Person::players[i]->coords.y + 1) {
3653                             Person::players[k]->animTarget = rabbitkickreversedanim;
3654                             Person::players[k]->animCurrent = rabbitkickreversedanim;
3655                             Person::players[i]->animCurrent = rabbitkickreversalanim;
3656                             Person::players[i]->animTarget = rabbitkickreversalanim;
3657                             Person::players[k]->frameCurrent = 1;
3658                             Person::players[k]->frameTarget = 2;
3659                             Person::players[i]->frameCurrent = 1;
3660                             Person::players[i]->frameTarget = 2;
3661                         }
3662                         Person::players[k]->target = 0;
3663                         Person::players[i]->oldcoords = Person::players[i]->coords;
3664                         Person::players[k]->coords = Person::players[i]->coords;
3665                         Person::players[i]->targetyaw = Person::players[k]->targetyaw;
3666                         Person::players[i]->yaw = Person::players[k]->targetyaw;
3667                         if (Person::players[i]->aitype == attacktypecutoff)
3668                             Person::players[i]->stunned = .5;
3669                     }
3670                 }
3671             }
3672         }
3673 }
3674
3675 void doAerialAcrobatics()
3676 {
3677     static XYZ facing, flatfacing;
3678     for (int k = 0; k < numplayers; k++) {
3679         Person::players[k]->turnspeed = 500;
3680
3681         if ((Person::players[k]->isRun() &&
3682                 ((Person::players[k]->targetyaw != rabbitrunninganim &&
3683                   Person::players[k]->targetyaw != wolfrunninganim) ||
3684                  Person::players[k]->frameTarget == 4)) ||
3685                 Person::players[k]->animTarget == removeknifeanim ||
3686                 Person::players[k]->animTarget == crouchremoveknifeanim ||
3687                 Person::players[k]->animTarget == flipanim ||
3688                 Person::players[k]->animTarget == fightsidestep ||
3689                 Person::players[k]->animTarget == walkanim) {
3690             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed);
3691         }
3692
3693
3694         if (Person::players[k]->isStop() ||
3695                 Person::players[k]->isLanding() ||
3696                 Person::players[k]->animTarget == staggerbackhighanim ||
3697                 (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent == sneakanim) ||
3698                 Person::players[k]->animTarget == staggerbackhardanim ||
3699                 Person::players[k]->animTarget == backhandspringanim ||
3700                 Person::players[k]->animTarget == dodgebackanim ||
3701                 Person::players[k]->animTarget == rollanim ||
3702                 (animation[Person::players[k]->animTarget].attack &&
3703                  Person::players[k]->animTarget != rabbitkickanim &&
3704                  (Person::players[k]->animTarget != crouchstabanim || Person::players[k]->hasvictim) &&
3705                  (Person::players[k]->animTarget != swordgroundstabanim || Person::players[k]->hasvictim))) {
3706             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 2);
3707         }
3708
3709         if (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent != sneakanim) {
3710             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 4);
3711         }
3712
3713         /*if(Person::players[k]->aitype!=passivetype||(distsq(&Person::players[k]->coords,&viewer)<viewdistance*viewdistance))*/
3714         Person::players[k]->DoStuff();
3715         if (Person::players[k]->immobile && k != 0)
3716             Person::players[k]->coords = Person::players[k]->realoldcoords;
3717
3718         //if player's position has changed (?)
3719         if (distsq(&Person::players[k]->coords, &Person::players[k]->realoldcoords) > 0 &&
3720                 !Person::players[k]->skeleton.free &&
3721                 Person::players[k]->animTarget != climbanim &&
3722                 Person::players[k]->animTarget != hanganim) {
3723             XYZ lowpoint, lowpointtarget, lowpoint2, lowpointtarget2, lowpoint3, lowpointtarget3, lowpoint4, lowpointtarget4, lowpoint5, lowpointtarget5, lowpoint6, lowpointtarget6, lowpoint7, lowpointtarget7, colpoint, colpoint2;
3724             int whichhit;
3725             bool tempcollide = 0;
3726
3727             if (Person::players[k]->collide < -.3)
3728                 Person::players[k]->collide = -.3;
3729             if (Person::players[k]->collide > 1)
3730                 Person::players[k]->collide = 1;
3731             Person::players[k]->collide -= multiplier * 30;
3732
3733             //clip to terrain
3734             Person::players[k]->coords.y = max(Person::players[k]->coords.y, terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z));
3735
3736             for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
3737                 int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
3738                 if (objects.type[i] != rocktype ||
3739                         objects.scale[i] > .5 && Person::players[k]->aitype == playercontrolled ||
3740                         objects.position[i].y > Person::players[k]->coords.y) {
3741                     lowpoint = Person::players[k]->coords;
3742                     if (Person::players[k]->animTarget != jumpupanim &&
3743                             Person::players[k]->animTarget != jumpdownanim &&
3744                             !Person::players[k]->isFlip())
3745                         lowpoint.y += 1.25;
3746                     else
3747                         lowpoint.y += 1.3;
3748                     if (     Person::players[k]->coords.y < terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) &&
3749                              Person::players[k]->coords.y > terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) - .1)
3750                         Person::players[k]->coords.y = terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z);
3751                     if (Person::players[k]->SphereCheck(&lowpoint, 1.3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
3752                         flatfacing = lowpoint - Person::players[k]->coords;
3753                         Person::players[k]->coords = lowpoint;
3754                         Person::players[k]->coords.y -= 1.3;
3755                         Person::players[k]->collide = 1;
3756                         tempcollide = 1;
3757                         //wall jumps
3758                         //TODO: refactor four similar blocks
3759                         if (Person::players[k]->aitype == playercontrolled &&
3760                                 (Person::players[k]->animTarget == jumpupanim ||
3761                                  Person::players[k]->animTarget == jumpdownanim ||
3762                                  Person::players[k]->isFlip()) &&
3763                                 !Person::players[k]->jumptogglekeydown &&
3764                                 Person::players[k]->jumpkeydown) {
3765                             lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, -90, 0) * 1.5;
3766                             XYZ tempcoords1 = lowpoint;
3767                             whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3768                             if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3769                                 Person::players[k]->setAnimation(walljumpleftanim);
3770                                 emit_sound_at(movewhooshsound, Person::players[k]->coords);
3771                                 if (k == 0)
3772                                     pause_sound(whooshsound);
3773
3774                                 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3775                                 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3776                                 if (lowpointtarget.z < 0)
3777                                     Person::players[k]->yaw = 180 - Person::players[k]->yaw;
3778                                 Person::players[k]->targetyaw = Person::players[k]->yaw;
3779                                 Person::players[k]->lowyaw = Person::players[k]->yaw;
3780                                 if (k == 0)
3781                                     numwallflipped++;
3782                             } else {
3783                                 lowpoint = tempcoords1;
3784                                 lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, 90, 0) * 1.5;
3785                                 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3786                                 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3787                                     Person::players[k]->setAnimation(walljumprightanim);
3788                                     emit_sound_at(movewhooshsound, Person::players[k]->coords);
3789                                     if (k == 0)
3790                                         pause_sound(whooshsound);
3791
3792                                     lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3793                                     Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3794                                     if (lowpointtarget.z < 0)
3795                                         Person::players[k]->yaw = 180 - Person::players[k]->yaw;
3796                                     Person::players[k]->targetyaw = Person::players[k]->yaw;
3797                                     Person::players[k]->lowyaw = Person::players[k]->yaw;
3798                                     if (k == 0)
3799                                         numwallflipped++;
3800                                 } else {
3801                                     lowpoint = tempcoords1;
3802                                     lowpointtarget = lowpoint + Person::players[k]->facing * 2;
3803                                     whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3804                                     if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3805                                         Person::players[k]->setAnimation(walljumpbackanim);
3806                                         emit_sound_at(movewhooshsound, Person::players[k]->coords);
3807                                         if (k == 0)
3808                                             pause_sound(whooshsound);
3809
3810                                         lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3811                                         Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3812                                         if (lowpointtarget.z < 0)
3813                                             Person::players[k]->yaw = 180 - Person::players[k]->yaw;
3814                                         Person::players[k]->targetyaw = Person::players[k]->yaw;
3815                                         Person::players[k]->lowyaw = Person::players[k]->yaw;
3816                                         if (k == 0)
3817                                             numwallflipped++;
3818                                     } else {
3819                                         lowpoint = tempcoords1;
3820                                         lowpointtarget = lowpoint - Person::players[k]->facing * 2;
3821                                         whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3822                                         if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3823                                             Person::players[k]->setAnimation(walljumpfrontanim);
3824                                             emit_sound_at(movewhooshsound, Person::players[k]->coords);
3825                                             if (k == 0)
3826                                                 pause_sound(whooshsound);
3827
3828                                             lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3829                                             Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3830                                             if (lowpointtarget.z < 0)
3831                                                 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
3832                                             Person::players[k]->yaw += 180;
3833                                             Person::players[k]->targetyaw = Person::players[k]->yaw;
3834                                             Person::players[k]->lowyaw = Person::players[k]->yaw;
3835                                             if (k == 0)
3836                                                 numwallflipped++;
3837                                         }
3838                                     }
3839                                 }
3840                             }
3841                         }
3842                     }
3843                 } else if (objects.type[i] == rocktype) {
3844                     lowpoint2 = Person::players[k]->coords;
3845                     lowpoint = Person::players[k]->coords;
3846                     lowpoint.y += 2;
3847                     if (objects.model[i].LineCheck(&lowpoint, &lowpoint2, &colpoint, &objects.position[i], &objects.yaw[i]) != -1) {
3848                         Person::players[k]->coords = colpoint;
3849                         Person::players[k]->collide = 1;
3850                         tempcollide = 1;
3851
3852                         if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) {
3853                             //flipped into a rock
3854                             if (Person::players[k]->isFlip() && animation[Person::players[k]->animTarget].label[Person::players[k]->frameTarget] == 7)
3855                                 Person::players[k]->RagDoll(0);
3856
3857                             if (Person::players[k]->animTarget == jumpupanim) {
3858                                 Person::players[k]->jumppower = -4;
3859                                 Person::players[k]->animTarget = Person::players[k]->getIdle();
3860                             }
3861                             Person::players[k]->target = 0;
3862                             Person::players[k]->frameTarget = 0;
3863                             Person::players[k]->onterrain = 1;
3864
3865                             if (Person::players[k]->id == 0) {
3866                                 pause_sound(whooshsound);
3867                                 OPENAL_SetVolume(channels[whooshsound], 0);
3868                             }
3869
3870                             //landing
3871                             if ((Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) && !Person::players[k]->wasLanding()) {
3872                                 if (Person::players[k]->isFlip())
3873                                     Person::players[k]->jumppower = -4;
3874                                 Person::players[k]->animTarget = Person::players[k]->getLanding();
3875                                 emit_sound_at(landsound, Person::players[k]->coords, 128.);
3876                                 if (k == 0) {
3877                                     envsound[numenvsounds] = Person::players[k]->coords;
3878                                     envsoundvol[numenvsounds] = 16;
3879                                     envsoundlife[numenvsounds] = .4;
3880                                     numenvsounds++;
3881                                 }
3882
3883                             }
3884                         }
3885                     }
3886                 }
3887             }
3888
3889             if (tempcollide && (/*Person::players[k]->jumptogglekeydown*/1 == 1 || Person::players[k]->aitype != playercontrolled))
3890                 for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
3891                     int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
3892                     lowpoint = Person::players[k]->coords;
3893                     lowpoint.y += 1.35;
3894                     if (objects.type[i] != rocktype)
3895                         if (Person::players[k]->SphereCheck(&lowpoint, 1.33, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
3896                             if (Person::players[k]->animTarget != jumpupanim &&
3897                                     Person::players[k]->animTarget != jumpdownanim &&
3898                                     Person::players[k]->onterrain)
3899                                 Person::players[k]->avoidcollided = 1;
3900                             Person::players[k]->coords = lowpoint;
3901                             Person::players[k]->coords.y -= 1.35;
3902                             Person::players[k]->collide = 1;
3903
3904                             if ((Person::players[k]->grabdelay <= 0 || Person::players[k]->aitype != playercontrolled) &&
3905                                     (Person::players[k]->animCurrent != climbanim &&
3906                                      Person::players[k]->animCurrent != hanganim &&
3907                                      !Person::players[k]->isWallJump() ||
3908                                      Person::players[k]->animTarget == jumpupanim ||
3909                                      Person::players[k]->animTarget == jumpdownanim)) {
3910                                 lowpoint = Person::players[k]->coords;
3911                                 objects.model[i].SphereCheckPossible(&lowpoint, 1.5, &objects.position[i], &objects.yaw[i]);
3912                                 lowpoint = Person::players[k]->coords;
3913                                 lowpoint.y += .05;
3914                                 facing = 0;
3915                                 facing.z = -1;
3916                                 facing = DoRotation(facing, 0, Person::players[k]->targetyaw + 180, 0);
3917                                 lowpointtarget = lowpoint + facing * 1.4;
3918                                 whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3919                                 if (whichhit != -1) {
3920                                     lowpoint = Person::players[k]->coords;
3921                                     lowpoint.y += .1;
3922                                     lowpointtarget = lowpoint + facing * 1.4;
3923                                     lowpoint2 = lowpoint;
3924                                     lowpointtarget2 = lowpointtarget;
3925                                     lowpoint3 = lowpoint;
3926                                     lowpointtarget3 = lowpointtarget;
3927                                     lowpoint4 = lowpoint;
3928                                     lowpointtarget4 = lowpointtarget;
3929                                     lowpoint5 = lowpoint;
3930                                     lowpointtarget5 = lowpointtarget;
3931                                     lowpoint6 = lowpoint;
3932                                     lowpointtarget6 = lowpointtarget;
3933                                     lowpoint7 = lowpoint;
3934                                     lowpointtarget7 = lowpoint;
3935                                     lowpoint2.x += .1;
3936                                     lowpointtarget2.x += .1;
3937                                     lowpoint3.z += .1;
3938                                     lowpointtarget3.z += .1;
3939                                     lowpoint4.x -= .1;
3940                                     lowpointtarget4.x -= .1;
3941                                     lowpoint5.z -= .1;
3942                                     lowpointtarget5.z -= .1;
3943                                     lowpoint6.y += 45 / 13;
3944                                     lowpointtarget6.y += 45 / 13;
3945                                     lowpointtarget6 += facing * .6;
3946                                     lowpointtarget7.y += 90 / 13;
3947                                     whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3948                                     if (objects.friction[i] > .5)
3949                                         if (whichhit != -1) {
3950                                             if (whichhit != -1 && Person::players[k]->animTarget != jumpupanim && Person::players[k]->animTarget != jumpdownanim)
3951                                                 Person::players[k]->collided = 1;
3952                                             if (checkcollide(lowpoint7, lowpointtarget7) == -1)
3953                                                 if (checkcollide(lowpoint6, lowpointtarget6) == -1)
3954                                                     if (     objects.model[i].LineCheckPossible(&lowpoint2, &lowpointtarget2,
3955                                                              &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3956                                                              objects.model[i].LineCheckPossible(&lowpoint3, &lowpointtarget3,
3957                                                                      &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3958                                                              objects.model[i].LineCheckPossible(&lowpoint4, &lowpointtarget4,
3959                                                                      &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3960                                                              objects.model[i].LineCheckPossible(&lowpoint5, &lowpointtarget5,
3961                                                                      &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
3962                                                         for (int j = 0; j < 45; j++) {
3963                                                             lowpoint = Person::players[k]->coords;
3964                                                             lowpoint.y += (float)j / 13;
3965                                                             lowpointtarget = lowpoint + facing * 1.4;
3966                                                             if (objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget,
3967                                                                                                    &colpoint2, &objects.position[i], &objects.yaw[i]) == -1) {
3968                                                                 if (j <= 6 || j <= 25 && Person::players[k]->animTarget == jumpdownanim)
3969                                                                     break;
3970                                                                 if (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim) {
3971                                                                     lowpoint = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[k], 0);
3972                                                                     lowpoint = Person::players[k]->coords;
3973                                                                     lowpoint.y += (float)j / 13;
3974                                                                     lowpointtarget = lowpoint + facing * 1.3;
3975                                                                     flatfacing = Person::players[k]->coords;
3976                                                                     Person::players[k]->coords = colpoint - DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[k], 0) * .01;
3977                                                                     Person::players[k]->coords.y = lowpointtarget.y - .07;
3978                                                                     Person::players[k]->currentoffset = (flatfacing - Person::players[k]->coords) / Person::players[k]->scale;
3979
3980                                                                     if (j > 10 || !Person::players[k]->isRun()) {
3981                                                                         if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->animTarget == jumpupanim) {
3982                                                                             if (k == 0)
3983                                                                                 pause_sound(whooshsound);
3984                                                                         }
3985                                                                         emit_sound_at(jumpsound, Person::players[k]->coords, 128.);
3986
3987                                                                         lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3988                                                                         Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3989                                                                         if (lowpointtarget.z < 0)
3990                                                                             Person::players[k]->yaw = 180 - Person::players[k]->yaw;
3991                                                                         Person::players[k]->targetyaw = Person::players[k]->yaw;
3992                                                                         Person::players[k]->lowyaw = Person::players[k]->yaw;
3993
3994                                                                         //Person::players[k]->velocity=lowpointtarget*.03;
3995                                                                         Person::players[k]->velocity = 0;
3996
3997                                                                         //climb ledge (?)
3998                                                                         if (Person::players[k]->animTarget == jumpupanim) {
3999                                                                             Person::players[k]->animTarget = climbanim;
4000                                                                             Person::players[k]->jumppower = 0;
4001                                                                             Person::players[k]->jumpclimb = 1;
4002                                                                         }
4003                                                                         Person::players[k]->transspeed = 6;
4004                                                                         Person::players[k]->target = 0;
4005                                                                         Person::players[k]->frameTarget = 1;
4006                                                                         //hang ledge (?)
4007                                                                         if (j > 25) {
4008                                                                             Person::players[k]->setAnimation(hanganim);
4009                                                                             Person::players[k]->jumppower = 0;
4010                                                                         }
4011                                                                     }
4012                                                                     break;
4013                                                                 }
4014                                                             }
4015                                                         }
4016                                         }
4017                                 }
4018                             }
4019                         }
4020                 }
4021             if (Person::players[k]->collide <= 0) {
4022                 //in the air
4023                 if (!Person::players[k]->onterrain &&
4024                         Person::players[k]->animTarget != jumpupanim &&
4025                         Person::players[k]->animTarget != jumpdownanim &&
4026                         Person::players[k]->animTarget != climbanim &&
4027                         Person::players[k]->animTarget != hanganim &&
4028                         !Person::players[k]->isWallJump() &&
4029                         !Person::players[k]->isFlip()) {
4030                     if (Person::players[k]->animCurrent != climbanim &&
4031                             Person::players[k]->animCurrent != tempanim &&
4032                             Person::players[k]->animTarget != backhandspringanim &&
4033                             (Person::players[k]->animTarget != rollanim ||
4034                              Person::players[k]->frameTarget < 2 ||
4035                              Person::players[k]->frameTarget > 6)) {
4036                         //stagger off ledge (?)
4037                         if (Person::players[k]->animTarget == staggerbackhighanim || Person::players[k]->animTarget == staggerbackhardanim)
4038                             Person::players[k]->RagDoll(0);
4039                         Person::players[k]->setAnimation(jumpdownanim);
4040
4041                         if (!k)
4042                             emit_sound_at(whooshsound, Person::players[k]->coords, 128.);
4043                     }
4044                     //gravity
4045                     Person::players[k]->velocity.y += gravity;
4046                 }
4047             }
4048         }
4049         Person::players[k]->realoldcoords = Person::players[k]->coords;
4050     }
4051 }
4052
4053 void doAttacks()
4054 {
4055     static XYZ relative;
4056     static int randattack;
4057     static bool playerrealattackkeydown = 0;
4058
4059     if (!Input::isKeyDown(attackkey))
4060         oldattackkey = 0;
4061     if (oldattackkey)
4062         Person::players[0]->attackkeydown = 0;
4063     if (oldattackkey)
4064         playerrealattackkeydown = 0;
4065     if (!oldattackkey)
4066         playerrealattackkeydown = Input::isKeyDown(attackkey);
4067     if ((Person::players[0]->parriedrecently <= 0 ||
4068             Person::players[0]->weaponactive == -1) &&
4069             (!oldattackkey ||
4070              (realthreat &&
4071               Person::players[0]->lastattack != swordslashanim &&
4072               Person::players[0]->lastattack != knifeslashstartanim &&
4073               Person::players[0]->lastattack != staffhitanim &&
4074               Person::players[0]->lastattack != staffspinhitanim)))
4075         Person::players[0]->attackkeydown = Input::isKeyDown(attackkey);
4076     if (Input::isKeyDown(attackkey) &&
4077             !oldattackkey &&
4078             !Person::players[0]->backkeydown) {
4079         for (int k = 0; k < numplayers; k++) {
4080             if ((Person::players[k]->animTarget == swordslashanim ||
4081                     Person::players[k]->animTarget == staffhitanim ||
4082                     Person::players[k]->animTarget == staffspinhitanim) &&
4083                     Person::players[0]->animCurrent != dodgebackanim &&
4084                     !Person::players[k]->skeleton.free)
4085                 Person::players[k]->Reverse();
4086         }
4087     }
4088
4089     if (!hostile || indialogue != -1)
4090         Person::players[0]->attackkeydown = 0;
4091
4092     for (int k = 0; k < numplayers; k++) {
4093         if (indialogue != -1)
4094             Person::players[k]->attackkeydown = 0;
4095         if (Person::players[k]->animTarget != rabbitrunninganim && Person::players[k]->animTarget != wolfrunninganim) {
4096             if (Person::players[k]->aitype != playercontrolled)
4097                 Person::players[k]->victim = Person::players[0];
4098             //attack key pressed
4099             if (Person::players[k]->attackkeydown) {
4100                 //dodge backward
4101                 if (Person::players[k]->backkeydown &&
4102                         Person::players[k]->animTarget != backhandspringanim &&
4103                         (Person::players[k]->isIdle() ||
4104                          Person::players[k]->isStop() ||
4105                          Person::players[k]->isRun() ||
4106                          Person::players[k]->animTarget == walkanim)) {
4107                     if (Person::players[k]->jumppower <= 1) {
4108                         Person::players[k]->jumppower -= 2;
4109                     } else {
4110                         for (int i = 0; i < numplayers; i++) {
4111                             if (i == k)
4112                                 continue;
4113                             if (Person::players[i]->animTarget == swordslashanim ||
4114                                     Person::players[i]->animTarget == knifeslashstartanim ||
4115                                     Person::players[i]->animTarget == staffhitanim ||
4116                                     Person::players[i]->animTarget == staffspinhitanim)
4117                                 if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < 6.5 && !Person::players[i]->skeleton.free) {
4118                                     Person::players[k]->setAnimation(dodgebackanim);
4119                                     Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
4120                                     Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
4121                                 }
4122                         }
4123                         if (Person::players[k]->animTarget != dodgebackanim) {
4124                             if (k == 0)
4125                                 numflipped++;
4126                             Person::players[k]->setAnimation(backhandspringanim);
4127                             Person::players[k]->targetyaw = -yaw + 180;
4128                             if (Person::players[k]->leftkeydown)
4129                                 Person::players[k]->targetyaw -= 45;
4130                             if (Person::players[k]->rightkeydown)
4131                                 Person::players[k]->targetyaw += 45;
4132                             Person::players[k]->yaw = Person::players[k]->targetyaw;
4133                             Person::players[k]->jumppower -= 2;
4134                         }
4135                     }
4136                 }
4137                 //attack
4138                 if (!animation[Person::players[k]->animTarget].attack &&
4139                         !Person::players[k]->backkeydown &&
4140                         (Person::players[k]->isIdle() ||
4141                          Person::players[k]->isRun() ||
4142                          Person::players[k]->animTarget == walkanim ||
4143                          Person::players[k]->animTarget == sneakanim ||
4144                          Person::players[k]->isCrouch())) {
4145                     const int attackweapon = Person::players[k]->weaponactive == -1 ? 0 : weapons[Person::players[k]->weaponids[Person::players[k]->weaponactive]].getType();
4146                     //normal attacks (?)
4147                     Person::players[k]->hasvictim = 0;
4148                     if (numplayers > 1)
4149                         for (int i = 0; i < numplayers; i++) {
4150                             if (i == k || !(k == 0 || i == 0))
4151                                 continue;
4152                             if (!Person::players[k]->hasvictim)
4153                                 if (animation[Person::players[k]->animTarget].attack != reversal) {
4154                                     //choose an attack
4155                                     const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
4156                                     if (distance < 4.5 &&
4157                                             !Person::players[i]->skeleton.free &&
4158                                             Person::players[i]->howactive < typedead1 &&
4159                                             Person::players[i]->animTarget != jumpreversedanim &&
4160                                             Person::players[i]->animTarget != rabbitkickreversedanim &&
4161                                             Person::players[i]->animTarget != rabbitkickanim &&
4162                                             Person::players[k]->animTarget != rabbitkickanim &&
4163                                             Person::players[i]->animTarget != getupfrombackanim &&
4164                                             (Person::players[i]->animTarget != staggerbackhighanim &&
4165                                              (Person::players[i]->animTarget != staggerbackhardanim ||
4166                                               animation[staggerbackhardanim].label[Person::players[i]->frameTarget] == 6)) &&
4167                                             Person::players[i]->animTarget != jumpdownanim &&
4168                                             Person::players[i]->animTarget != jumpupanim &&
4169                                             Person::players[i]->animTarget != getupfromfrontanim) {
4170                                         Person::players[k]->victim = Person::players[i];
4171                                         Person::players[k]->hasvictim = 1;
4172                                         if (Person::players[k]->aitype == playercontrolled) { //human player
4173                                             //sweep
4174                                             if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4175                                                     Person::players[k]->crouchkeydown &&
4176                                                     animation[Person::players[i]->animTarget].height != lowheight)
4177                                                 Person::players[k]->animTarget = sweepanim;
4178                                             //winduppunch
4179                                             else if (distance < 1.5 * sq(Person::players[k]->scale * 5) &&
4180                                                      animation[Person::players[i]->animTarget].height != lowheight &&
4181                                                      !Person::players[k]->forwardkeydown &&
4182                                                      !Person::players[k]->leftkeydown &&
4183                                                      !Person::players[k]->rightkeydown &&
4184                                                      !Person::players[k]->crouchkeydown &&
4185                                                      !attackweapon &&
4186                                                      !reversaltrain)
4187                                                 Person::players[k]->animTarget = winduppunchanim;
4188                                             //upunch
4189                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4190                                                      animation[Person::players[i]->animTarget].height != lowheight &&
4191                                                      !Person::players[k]->forwardkeydown &&
4192                                                      !Person::players[k]->leftkeydown &&
4193                                                      !Person::players[k]->rightkeydown &&
4194                                                      !Person::players[k]->crouchkeydown &&
4195                                                      !attackweapon)
4196                                                 Person::players[k]->animTarget = upunchanim;
4197                                             //knifefollow
4198                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4199                                                      Person::players[i]->staggerdelay > 0 &&
4200                                                      attackweapon == knife &&
4201                                                      Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2)
4202                                                 Person::players[k]->animTarget = knifefollowanim;
4203                                             //knifeslashstart
4204                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4205                                                      animation[Person::players[i]->animTarget].height != lowheight &&
4206                                                      !Person::players[k]->forwardkeydown &&
4207                                                      !Person::players[k]->leftkeydown &&
4208                                                      !Person::players[k]->rightkeydown &&
4209                                                      !Person::players[k]->crouchkeydown &&
4210                                                      attackweapon == knife &&
4211                                                      Person::players[k]->weaponmissdelay <= 0)
4212                                                 Person::players[k]->animTarget = knifeslashstartanim;
4213                                             //swordslash
4214                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
4215                                                      animation[Person::players[i]->animTarget].height != lowheight &&
4216                                                      !Person::players[k]->crouchkeydown &&
4217                                                      attackweapon == sword &&
4218                                                      Person::players[k]->weaponmissdelay <= 0)
4219                                                 Person::players[k]->animTarget = swordslashanim;
4220                                             //staffhit
4221                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
4222                                                      animation[Person::players[i]->animTarget].height != lowheight &&
4223                                                      !Person::players[k]->crouchkeydown &&
4224                                                      attackweapon == staff &&
4225                                                      Person::players[k]->weaponmissdelay <= 0 &&
4226                                                      !Person::players[k]->leftkeydown &&
4227                                                      !Person::players[k]->rightkeydown &&
4228                                                      !Person::players[k]->forwardkeydown)
4229                                                 Person::players[k]->animTarget = staffhitanim;
4230                                             //staffspinhit
4231                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
4232                                                      animation[Person::players[i]->animTarget].height != lowheight &&
4233                                                      !Person::players[k]->crouchkeydown &&
4234                                                      attackweapon == staff &&
4235                                                      Person::players[k]->weaponmissdelay <= 0)
4236                                                 Person::players[k]->animTarget = staffspinhitanim;
4237                                             //spinkick
4238                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4239                                                      animation[Person::players[i]->animTarget].height != lowheight)
4240                                                 Person::players[k]->animTarget = spinkickanim;
4241                                             //lowkick
4242                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4243                                                      animation[Person::players[i]->animTarget].height == lowheight &&
4244                                                      animation[Person::players[k]->animTarget].attack != normalattack)
4245                                                 Person::players[k]->animTarget = lowkickanim;
4246                                         } else { //AI player
4247                                             if (distance < 4.5 * sq(Person::players[k]->scale * 5)) {
4248                                                 randattack = abs(Random() % 5);
4249                                                 if (!attackweapon && distance < 2.5 * sq(Person::players[k]->scale * 5)) {
4250                                                     //sweep
4251                                                     if (randattack == 0 && animation[Person::players[i]->animTarget].height != lowheight)
4252                                                         Person::players[k]->animTarget = sweepanim;
4253                                                     //upunch
4254                                                     else if (randattack == 1 && animation[Person::players[i]->animTarget].height != lowheight &&
4255                                                              !attackweapon)
4256                                                         Person::players[k]->animTarget = upunchanim;
4257                                                     //spinkick
4258                                                     else if (randattack == 2 && animation[Person::players[i]->animTarget].height != lowheight)
4259                                                         Person::players[k]->animTarget = spinkickanim;
4260                                                     //lowkick
4261                                                     else if (animation[Person::players[i]->animTarget].height == lowheight)
4262                                                         Person::players[k]->animTarget = lowkickanim;
4263                                                 }
4264                                                 if (attackweapon) {
4265                                                     //sweep
4266                                                     if ((tutoriallevel != 1 || !attackweapon) &&
4267                                                             distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4268                                                             randattack == 0 &&
4269                                                             animation[Person::players[i]->animTarget].height != lowheight)
4270                                                         Person::players[k]->animTarget = sweepanim;
4271                                                     //knifeslashstart
4272                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4273                                                              attackweapon == knife &&
4274                                                              Person::players[k]->weaponmissdelay <= 0)
4275                                                         Person::players[k]->animTarget = knifeslashstartanim;
4276                                                     //swordslash
4277                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
4278                                                                Person::players[0]->hasvictim &&
4279                                                                Person::players[0]->animTarget == swordslashanim) &&
4280                                                              attackweapon == sword &&
4281                                                              Person::players[k]->weaponmissdelay <= 0)
4282                                                         Person::players[k]->animTarget = swordslashanim;
4283                                                     //staffhit
4284                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
4285                                                                Person::players[0]->hasvictim &&
4286                                                                Person::players[0]->animTarget == swordslashanim) &&
4287                                                              attackweapon == staff &&
4288                                                              Person::players[k]->weaponmissdelay <= 0 &&
4289                                                              randattack < 3)
4290                                                         Person::players[k]->animTarget = staffhitanim;
4291                                                     //staffspinhit
4292                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
4293                                                                Person::players[0]->hasvictim &&
4294                                                                Person::players[0]->animTarget == swordslashanim) &&
4295                                                              attackweapon == staff &&
4296                                                              Person::players[k]->weaponmissdelay <= 0 &&
4297                                                              randattack >= 3)
4298                                                         Person::players[k]->animTarget = staffspinhitanim;
4299                                                     //spinkick
4300                                                     else if ((tutoriallevel != 1 || !attackweapon) &&
4301                                                              distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4302                                                              randattack == 1 &&
4303                                                              animation[Person::players[i]->animTarget].height != lowheight)
4304                                                         Person::players[k]->animTarget = spinkickanim;
4305                                                     //lowkick
4306                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
4307                                                              animation[Person::players[i]->animTarget].height == lowheight &&
4308                                                              animation[Person::players[k]->animTarget].attack != normalattack)
4309                                                         Person::players[k]->animTarget = lowkickanim;
4310                                                 }
4311                                             }
4312                                         }
4313                                         //upunch becomes wolfslap
4314                                         if (Person::players[k]->animTarget == upunchanim && Person::players[k]->creature == wolftype)
4315                                             Person::players[k]->animTarget = wolfslapanim;
4316                                     }
4317                                     //sneak attacks
4318                                     if ((k == 0) && (tutoriallevel != 1 || tutorialstage == 22) &&
4319                                             Person::players[i]->howactive < typedead1 &&
4320                                             distance < 1.5 * sq(Person::players[k]->scale * 5) &&
4321                                             !Person::players[i]->skeleton.free &&
4322                                             Person::players[i]->animTarget != getupfrombackanim &&
4323                                             Person::players[i]->animTarget != getupfromfrontanim &&
4324                                             (Person::players[i]->stunned > 0 && Person::players[k]->madskills ||
4325                                              Person::players[i]->surprised > 0 ||
4326                                              Person::players[i]->aitype == passivetype ||
4327                                              attackweapon && Person::players[i]->stunned > 0) &&
4328                                             normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[k]->coords) > 0) {
4329                                         //sneakattack
4330                                         if (!attackweapon) {
4331                                             Person::players[k]->animCurrent = sneakattackanim;
4332                                             Person::players[k]->animTarget = sneakattackanim;
4333                                             Person::players[i]->animCurrent = sneakattackedanim;
4334                                             Person::players[i]->animTarget = sneakattackedanim;
4335                                             Person::players[k]->oldcoords = Person::players[k]->coords;
4336                                             Person::players[k]->coords = Person::players[i]->coords;
4337                                         }
4338                                         //knifesneakattack
4339                                         if (attackweapon == knife) {
4340                                             Person::players[k]->animCurrent = knifesneakattackanim;
4341                                             Person::players[k]->animTarget = knifesneakattackanim;
4342                                             Person::players[i]->animCurrent = knifesneakattackedanim;
4343                                             Person::players[i]->animTarget = knifesneakattackedanim;
4344                                             Person::players[i]->oldcoords = Person::players[i]->coords;
4345                                             Person::players[i]->coords = Person::players[k]->coords;
4346                                         }
4347                                         //swordsneakattack
4348                                         if (attackweapon == sword) {
4349                                             Person::players[k]->animCurrent = swordsneakattackanim;
4350                                             Person::players[k]->animTarget = swordsneakattackanim;
4351                                             Person::players[i]->animCurrent = swordsneakattackedanim;
4352                                             Person::players[i]->animTarget = swordsneakattackedanim;
4353                                             Person::players[i]->oldcoords = Person::players[i]->coords;
4354                                             Person::players[i]->coords = Person::players[k]->coords;
4355                                         }
4356                                         if (attackweapon != staff) {
4357                                             Person::players[k]->victim = Person::players[i];
4358                                             Person::players[k]->hasvictim = 1;
4359                                             Person::players[i]->targettilt2 = 0;
4360                                             Person::players[i]->frameTarget = 1;
4361                                             Person::players[i]->frameCurrent = 0;
4362                                             Person::players[i]->target = 0;
4363                                             Person::players[i]->velocity = 0;
4364                                             Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
4365                                             Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
4366                                             Person::players[k]->frameTarget = Person::players[i]->frameTarget;
4367                                             Person::players[k]->target = Person::players[i]->target;
4368                                             Person::players[k]->velocity = 0;
4369                                             Person::players[k]->targetyaw = Person::players[i]->yaw;
4370                                             Person::players[k]->yaw = Person::players[i]->yaw;
4371                                             Person::players[i]->targetyaw = Person::players[i]->yaw;
4372                                         }
4373                                     }
4374                                     if (animation[Person::players[k]->animTarget].attack == normalattack &&
4375                                             Person::players[k]->victim == Person::players[i] &&
4376                                             (!Person::players[i]->skeleton.free)) {
4377                                         oldattackkey = 1;
4378                                         Person::players[k]->frameTarget = 0;
4379                                         Person::players[k]->target = 0;
4380
4381                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
4382                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
4383                                         Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
4384                                         Person::players[k]->lastattack2 = Person::players[k]->lastattack;
4385                                         Person::players[k]->lastattack = Person::players[k]->animTarget;
4386                                     }
4387                                     if (Person::players[k]->animTarget == knifefollowanim &&
4388                                             Person::players[k]->victim == Person::players[i]) {
4389                                         oldattackkey = 1;
4390                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
4391                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
4392                                         Person::players[k]->victim = Person::players[i];
4393                                         Person::players[k]->hasvictim = 1;
4394                                         Person::players[i]->animTarget = knifefollowedanim;
4395                                         Person::players[i]->animCurrent = knifefollowedanim;
4396                                         Person::players[i]->targettilt2 = 0;
4397                                         Person::players[i]->targettilt2 = Person::players[k]->targettilt2;
4398                                         Person::players[i]->frameTarget = 1;
4399                                         Person::players[i]->frameCurrent = 0;
4400                                         Person::players[i]->target = 0;
4401                                         Person::players[i]->velocity = 0;
4402                                         Person::players[k]->animCurrent = knifefollowanim;
4403                                         Person::players[k]->animTarget = knifefollowanim;
4404                                         Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
4405                                         Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
4406                                         Person::players[k]->frameTarget = Person::players[i]->frameTarget;
4407                                         Person::players[k]->target = Person::players[i]->target;
4408                                         Person::players[k]->velocity = 0;
4409                                         Person::players[k]->oldcoords = Person::players[k]->coords;
4410                                         Person::players[i]->coords = Person::players[k]->coords;
4411                                         Person::players[i]->targetyaw = Person::players[k]->targetyaw;
4412                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
4413                                         Person::players[k]->yaw = Person::players[k]->targetyaw;
4414                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
4415                                     }
4416                                 }
4417                         }
4418                     const bool hasstaff = attackweapon == staff;
4419                     if (k == 0 && numplayers > 1)
4420                         for (int i = 0; i < numplayers; i++) {
4421                             if (i == k)
4422                                 continue;
4423                             if ((playerrealattackkeydown || Person::players[i]->dead || !hasstaff) &&
4424                                     animation[Person::players[k]->animTarget].attack == neutral) {
4425                                 const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
4426                                 if (!Person::players[i]->dead || !realthreat || (!attackweapon && Person::players[k]->crouchkeydown))
4427                                     if (Person::players[i]->skeleton.free)
4428                                         if (distance < 3.5 * sq(Person::players[k]->scale * 5) &&
4429                                                 (Person::players[i]->dead ||
4430                                                  Person::players[i]->skeleton.longdead > 1000 ||
4431                                                  Person::players[k]->isRun() ||
4432                                                  hasstaff ||
4433                                                  (attackweapon &&
4434                                                   (Person::players[i]->skeleton.longdead > 2000 ||
4435                                                    Person::players[i]->damage > Person::players[i]->damagetolerance / 8 ||
4436                                                    Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2) &&
4437                                                   distance < 1.5 * sq(Person::players[k]->scale * 5)))) {
4438                                             Person::players[k]->victim = Person::players[i];
4439                                             Person::players[k]->hasvictim = 1;
4440                                             if (attackweapon && tutoriallevel != 1) {
4441                                                 //crouchstab
4442                                                 if (Person::players[k]->crouchkeydown && attackweapon == knife && distance < 1.5 * sq(Person::players[k]->scale * 5))
4443                                                     Person::players[k]->animTarget = crouchstabanim;
4444                                                 //swordgroundstab
4445                                                 if (Person::players[k]->crouchkeydown && distance < 1.5 * sq(Person::players[k]->scale * 5) && attackweapon == sword)
4446                                                     Person::players[k]->animTarget = swordgroundstabanim;
4447                                                 //staffgroundsmash
4448                                                 if (distance < 3.5 * sq(Person::players[k]->scale * 5) && attackweapon == staff)
4449                                                     Person::players[k]->animTarget = staffgroundsmashanim;
4450                                             }
4451                                             if (distance < 2.5 &&
4452                                                     Person::players[k]->crouchkeydown &&
4453                                                     Person::players[k]->animTarget != crouchstabanim &&
4454                                                     !attackweapon &&
4455                                                     Person::players[i]->dead &&
4456                                                     Person::players[i]->skeleton.free &&
4457                                                     Person::players[i]->skeleton.longdead > 1000) {
4458                                                 Person::players[k]->animTarget = killanim;
4459                                                 //TODO: refactor this out, what does it do?
4460                                                 for (int j = 0; j < terrain.numdecals; j++) {
4461                                                     if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
4462                                                             terrain.decalalivetime[j] < 2)
4463                                                         terrain.DeleteDecal(j);
4464                                                 }
4465                                                 for (int l = 0; l < objects.numobjects; l++) {
4466                                                     if (objects.model[l].type == decalstype)
4467                                                         for (int j = 0; j < objects.model[l].numdecals; j++) {
4468                                                             if ((objects.model[l].decaltype[j] == blooddecal ||
4469                                                                     objects.model[l].decaltype[j] == blooddecalslow) &&
4470                                                                     objects.model[l].decalalivetime[j] < 2)
4471                                                                 objects.model[l].DeleteDecal(j);
4472                                                         }
4473                                                 }
4474                                             }
4475                                             if (!Person::players[i]->dead || musictype != 2)
4476                                                 if (distance < 3.5 &&
4477                                                         (Person::players[k]->isRun() || Person::players[k]->isIdle() && Person::players[k]->attackkeydown) &&
4478                                                         Person::players[k]->staggerdelay <= 0 &&
4479                                                         (Person::players[i]->dead ||
4480                                                          Person::players[i]->skeleton.longdead < 300 &&
4481                                                          Person::players[k]->lastattack != spinkickanim &&
4482                                                          Person::players[i]->skeleton.free) &&
4483                                                         (!Person::players[i]->dead || musictype != stream_fighttheme)) {
4484                                                     Person::players[k]->animTarget = dropkickanim;
4485                                                     for (int j = 0; j < terrain.numdecals; j++) {
4486                                                         if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
4487                                                                 terrain.decalalivetime[j] < 2) {
4488                                                             terrain.DeleteDecal(j);
4489                                                         }
4490                                                     }
4491                                                     for (int l = 0; l < objects.numobjects; l++) {
4492                                                         if (objects.model[l].type == decalstype)
4493                                                             for (int j = 0; j < objects.model[l].numdecals; j++) {
4494                                                                 if ((objects.model[l].decaltype[j] == blooddecal ||
4495                                                                         objects.model[l].decaltype[j] == blooddecalslow) &&
4496                                                                         objects.model[l].decalalivetime[j] < 2) {
4497                                                                     objects.model[l].DeleteDecal(j);
4498                                                                 }
4499                                                             }
4500                                                     }
4501                                                 }
4502                                         }
4503                                 if (animation[Person::players[k]->animTarget].attack == normalattack &&
4504                                         Person::players[k]->victim == Person::players[i] &&
4505                                         (!Person::players[i]->skeleton.free ||
4506                                          Person::players[k]->animTarget == killanim ||
4507                                          Person::players[k]->animTarget == crouchstabanim ||
4508                                          Person::players[k]->animTarget == swordgroundstabanim ||
4509                                          Person::players[k]->animTarget == staffgroundsmashanim ||
4510                                          Person::players[k]->animTarget == dropkickanim)) {
4511                                     oldattackkey = 1;
4512                                     Person::players[k]->frameTarget = 0;
4513                                     Person::players[k]->target = 0;
4514
4515                                     XYZ targetpoint = Person::players[i]->coords;
4516                                     if (Person::players[k]->animTarget == crouchstabanim ||
4517                                             Person::players[k]->animTarget == swordgroundstabanim ||
4518                                             Person::players[k]->animTarget == staffgroundsmashanim) {
4519                                         targetpoint += (Person::players[i]->jointPos(abdomen) +
4520                                                         Person::players[i]->jointPos(neck)) / 2 *
4521                                                        Person::players[i]->scale;
4522                                     }
4523                                     Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, targetpoint);
4524                                     Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, targetpoint);
4525
4526                                     if (Person::players[k]->animTarget == crouchstabanim || Person::players[k]->animTarget == swordgroundstabanim) {
4527                                         Person::players[k]->targetyaw += (float)(abs(Random() % 100) - 50) / 4;
4528                                     }
4529
4530                                     if (Person::players[k]->animTarget == staffgroundsmashanim)
4531                                         Person::players[k]->targettilt2 += 10;
4532
4533                                     Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
4534                                     Person::players[k]->lastattack2 = Person::players[k]->lastattack;
4535                                     Person::players[k]->lastattack = Person::players[k]->animTarget;
4536
4537                                     if (Person::players[k]->animTarget == swordgroundstabanim) {
4538                                         Person::players[k]->targetyaw += 30;
4539                                     }
4540                                 }
4541                             }
4542                         }
4543                     if (!Person::players[k]->hasvictim) {
4544                         //find victim
4545                         for (int i = 0; i < numplayers; i++) {
4546                             if (i == k || !(i == 0 || k == 0))
4547                                 continue;
4548                             if (!Person::players[i]->skeleton.free) {
4549                                 if (Person::players[k]->hasvictim) {
4550                                     if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) <
4551                                             distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords))
4552                                         Person::players[k]->victim = Person::players[i];
4553                                 } else {
4554                                     Person::players[k]->victim = Person::players[i];
4555                                     Person::players[k]->hasvictim = 1;
4556                                 }
4557                             }
4558                         }
4559                     }
4560                     if (Person::players[k]->aitype == playercontrolled)
4561                         //rabbit kick
4562                         if (Person::players[k]->attackkeydown &&
4563                                 Person::players[k]->isRun() &&
4564                                 Person::players[k]->wasRun() &&
4565                                 ((Person::players[k]->hasvictim &&
4566                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) < 12 * sq(Person::players[k]->scale * 5) &&
4567                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) > 7 * sq(Person::players[k]->scale * 5) &&
4568                                   !Person::players[k]->victim->skeleton.free &&
4569                                   Person::players[k]->victim->animTarget != getupfrombackanim &&
4570                                   Person::players[k]->victim->animTarget != getupfromfrontanim &&
4571                                   animation[Person::players[k]->victim->animTarget].height != lowheight &&
4572                                   Person::players[k]->aitype != playercontrolled && //wat???
4573                                   normaldotproduct(Person::players[k]->facing, Person::players[k]->victim->coords - Person::players[k]->coords) > 0 &&
4574                                   Person::players[k]->rabbitkickenabled) ||
4575                                  Person::players[k]->jumpkeydown)) {
4576                             oldattackkey = 1;
4577                             Person::players[k]->setAnimation(rabbitkickanim);
4578                         }
4579                     //update counts
4580                     if (animation[Person::players[k]->animTarget].attack && k == 0) {
4581                         numattacks++;
4582                         switch (attackweapon) {
4583                         case 0:
4584                             numunarmedattack++;
4585                             break;
4586                         case knife:
4587                             numknifeattack++;
4588                             break;
4589                         case sword:
4590                             numswordattack++;
4591                             break;
4592                         case staff:
4593                             numstaffattack++;
4594                             break;
4595                         }
4596                     }
4597                 }
4598             }
4599         }
4600     }
4601 }
4602
4603 void doPlayerCollisions()
4604 {
4605     static XYZ rotatetarget;
4606     static float collisionradius;
4607     if (numplayers > 1)
4608         for (int k = 0; k < numplayers; k++)
4609             for (int i = k + 1; i < numplayers; i++) {
4610                 //neither player is part of a reversal
4611                 if ((animation[Person::players[i]->animTarget].attack != reversed &&
4612                         animation[Person::players[i]->animTarget].attack != reversal &&
4613                         animation[Person::players[k]->animTarget].attack != reversed &&
4614                         animation[Person::players[k]->animTarget].attack != reversal) || (i != 0 && k != 0))
4615                     if ((animation[Person::players[i]->animCurrent].attack != reversed &&
4616                             animation[Person::players[i]->animCurrent].attack != reversal &&
4617                             animation[Person::players[k]->animCurrent].attack != reversed &&
4618                             animation[Person::players[k]->animCurrent].attack != reversal) || (i != 0 && k != 0))
4619                         //neither is sleeping
4620                         if (Person::players[i]->howactive <= typesleeping && Person::players[k]->howactive <= typesleeping)
4621                             if (Person::players[i]->howactive != typesittingwall && Person::players[k]->howactive != typesittingwall)
4622                                 //in same patch, neither is climbing
4623                                 if (Person::players[i]->whichpatchx == Person::players[k]->whichpatchx &&
4624                                         Person::players[i]->whichpatchz == Person::players[k]->whichpatchz &&
4625                                         Person::players[k]->skeleton.oldfree == Person::players[k]->skeleton.free &&
4626                                         Person::players[i]->skeleton.oldfree == Person::players[i]->skeleton.free &&
4627                                         Person::players[i]->animTarget != climbanim &&
4628                                         Person::players[i]->animTarget != hanganim &&
4629                                         Person::players[k]->animTarget != climbanim &&
4630                                         Person::players[k]->animTarget != hanganim)
4631                                     //players are close (bounding box test)
4632                                     if (Person::players[i]->coords.y > Person::players[k]->coords.y - 3)
4633                                         if (Person::players[i]->coords.y < Person::players[k]->coords.y + 3)
4634                                             if (Person::players[i]->coords.x > Person::players[k]->coords.x - 3)
4635                                                 if (Person::players[i]->coords.x < Person::players[k]->coords.x + 3)
4636                                                     if (Person::players[i]->coords.z > Person::players[k]->coords.z - 3)
4637                                                         if (Person::players[i]->coords.z < Person::players[k]->coords.z + 3) {
4638                                                             //spread fire from player to player
4639                                                             if (distsq(&Person::players[i]->coords, &Person::players[k]->coords)
4640                                                                     < 3 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
4641                                                                 if (Person::players[i]->onfire || Person::players[k]->onfire) {
4642                                                                     if (!Person::players[i]->onfire)
4643                                                                         Person::players[i]->CatchFire();
4644                                                                     if (!Person::players[k]->onfire)
4645                                                                         Person::players[k]->CatchFire();
4646                                                                 }
4647                                                             }
4648
4649                                                             XYZ tempcoords1 = Person::players[i]->coords;
4650                                                             XYZ tempcoords2 = Person::players[k]->coords;
4651                                                             if (!Person::players[i]->skeleton.oldfree)
4652                                                                 tempcoords1.y += Person::players[i]->jointPos(abdomen).y * Person::players[i]->scale;
4653                                                             if (!Person::players[k]->skeleton.oldfree)
4654                                                                 tempcoords2.y += Person::players[k]->jointPos(abdomen).y * Person::players[k]->scale;
4655                                                             collisionradius = 1.2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
4656                                                             if (Person::players[0]->hasvictim)
4657                                                                 if (Person::players[0]->animTarget == rabbitkickanim && (k == 0 || i == 0) && !Person::players[0]->victim->skeleton.free)
4658                                                                     collisionradius = 3;
4659                                                             if ((!Person::players[i]->skeleton.oldfree || !Person::players[k]->skeleton.oldfree) &&
4660                                                                     (distsq(&tempcoords1, &tempcoords2) < collisionradius ||
4661                                                                      distsq(&Person::players[i]->coords, &Person::players[k]->coords) < collisionradius)) {
4662                                                                 //jump down on a dead body
4663                                                                 if (k == 0 || i == 0) {
4664                                                                     int l = i ? i : k;
4665                                                                     if (Person::players[0]->animTarget == jumpdownanim &&
4666                                                                             !Person::players[0]->skeleton.oldfree &&
4667                                                                             !Person::players[0]->skeleton.free &&
4668                                                                             Person::players[l]->skeleton.oldfree &&
4669                                                                             Person::players[l]->skeleton.free &&
4670                                                                             Person::players[l]->dead &&
4671                                                                             Person::players[0]->lastcollide <= 0 &&
4672                                                                             fabs(Person::players[l]->coords.y - Person::players[0]->coords.y) < .2 &&
4673                                                                             distsq(&Person::players[0]->coords, &Person::players[l]->coords) < .7 * sq((Person::players[l]->scale + Person::players[0]->scale) * 2.5)) {
4674                                                                         Person::players[0]->coords.y = Person::players[l]->coords.y;
4675                                                                         Person::players[l]->velocity = Person::players[0]->velocity;
4676                                                                         Person::players[l]->skeleton.free = 0;
4677                                                                         Person::players[l]->yaw = 0;
4678                                                                         Person::players[l]->RagDoll(0);
4679                                                                         Person::players[l]->DoDamage(20);
4680                                                                         camerashake += .3;
4681                                                                         Person::players[l]->skeleton.longdead = 0;
4682                                                                         Person::players[0]->lastcollide = 1;
4683                                                                     }
4684                                                                 }
4685
4686                                                                 if (     (Person::players[i]->skeleton.oldfree == 1 && findLengthfast(&Person::players[i]->velocity) > 1) ||
4687                                                                          (Person::players[k]->skeleton.oldfree == 1 && findLengthfast(&Person::players[k]->velocity) > 1) ||
4688                                                                          (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0)) {
4689                                                                     rotatetarget = Person::players[k]->velocity - Person::players[i]->velocity;
4690                                                                     if ((Person::players[i]->animTarget != getupfrombackanim && Person::players[i]->animTarget != getupfromfrontanim ||
4691                                                                             Person::players[i]->skeleton.free) &&
4692                                                                             (Person::players[k]->animTarget != getupfrombackanim && Person::players[k]->animTarget != getupfromfrontanim ||
4693                                                                              Person::players[k]->skeleton.free))
4694                                                                         if ((((k != 0 && findLengthfast(&rotatetarget) > 150 ||
4695                                                                                 k == 0 && findLengthfast(&rotatetarget) > 50 && Person::players[0]->rabbitkickragdoll) &&
4696                                                                                 normaldotproduct(rotatetarget, Person::players[k]->coords - Person::players[i]->coords) > 0) &&
4697                                                                                 (k == 0 ||
4698                                                                                  k != 0 && Person::players[i]->skeleton.oldfree == 1 && animation[Person::players[k]->animCurrent].attack == neutral ||
4699                                                                                  /*i!=0&&*/Person::players[k]->skeleton.oldfree == 1 && animation[Person::players[i]->animCurrent].attack == neutral)) ||
4700                                                                                 (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) &&
4701                                                                                 (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) &&
4702                                                                                 k == 0 && !Person::players[i]->skeleton.oldfree && !Person::players[k]->skeleton.oldfree) {
4703                                                                             //If hit by body
4704                                                                             if (     (i != 0 || Person::players[i]->skeleton.free) &&
4705                                                                                      (k != 0 || Person::players[k]->skeleton.free) ||
4706                                                                                      (animation[Person::players[i]->animTarget].height == highheight &&
4707                                                                                       animation[Person::players[k]->animTarget].height == highheight)) {
4708                                                                                 if (tutoriallevel != 1) {
4709                                                                                     emit_sound_at(heavyimpactsound, Person::players[i]->coords);
4710                                                                                 }
4711
4712                                                                                 Person::players[i]->RagDoll(0);
4713                                                                                 if (Person::players[i]->damage > Person::players[i]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[i]->dead) {
4714                                                                                     award_bonus(0, aimbonus);
4715                                                                                 }
4716                                                                                 Person::players[i]->DoDamage(findLengthfast(&rotatetarget) / 4);
4717                                                                                 Person::players[k]->RagDoll(0);
4718                                                                                 if (Person::players[k]->damage > Person::players[k]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[k]->dead) {
4719                                                                                     award_bonus(0, aimbonus); // Huh, again?
4720                                                                                 }
4721                                                                                 Person::players[k]->DoDamage(findLengthfast(&rotatetarget) / 4);
4722
4723                                                                                 for (int j = 0; j < Person::players[i]->skeleton.num_joints; j++) {
4724                                                                                     Person::players[i]->skeleton.joints[j].velocity = Person::players[i]->skeleton.joints[j].velocity / 5 + Person::players[k]->velocity;
4725                                                                                 }
4726                                                                                 for (int j = 0; j < Person::players[k]->skeleton.num_joints; j++) {
4727                                                                                     Person::players[k]->skeleton.joints[j].velocity = Person::players[k]->skeleton.joints[j].velocity / 5 + Person::players[i]->velocity;
4728                                                                                 }
4729
4730                                                                             }
4731                                                                         }
4732                                                                     if (     (animation[Person::players[i]->animTarget].attack == neutral ||
4733                                                                               animation[Person::players[i]->animTarget].attack == normalattack) &&
4734                                                                              (animation[Person::players[k]->animTarget].attack == neutral ||
4735                                                                               animation[Person::players[k]->animTarget].attack == normalattack)) {
4736                                                                         //If bumped
4737                                                                         if (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0) {
4738                                                                             if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < .5 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
4739                                                                                 rotatetarget = Person::players[k]->coords - Person::players[i]->coords;
4740                                                                                 Normalise(&rotatetarget);
4741                                                                                 Person::players[k]->coords = (Person::players[k]->coords + Person::players[i]->coords) / 2;
4742                                                                                 Person::players[i]->coords = Person::players[k]->coords - rotatetarget * fast_sqrt(.6) / 2
4743                                                                                                    * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
4744                                                                                 Person::players[k]->coords += rotatetarget * fast_sqrt(.6) / 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
4745                                                                                 if (Person::players[k]->howactive == typeactive || hostile)
4746                                                                                     if (Person::players[k]->isIdle()) {
4747                                                                                         if (Person::players[k]->howactive < typesleeping)
4748                                                                                             Person::players[k]->setAnimation(Person::players[k]->getStop());
4749                                                                                         else if (Person::players[k]->howactive == typesleeping)
4750                                                                                             Person::players[k]->setAnimation(getupfromfrontanim);
4751                                                                                         if (!editorenabled)
4752                                                                                             Person::players[k]->howactive = typeactive;
4753                                                                                     }
4754                                                                                 if (Person::players[i]->howactive == typeactive || hostile)
4755                                                                                     if (Person::players[i]->isIdle()) {
4756                                                                                         if (Person::players[i]->howactive < typesleeping)
4757                                                                                             Person::players[i]->setAnimation(Person::players[k]->getStop());
4758                                                                                         else
4759                                                                                             Person::players[i]->setAnimation(getupfromfrontanim);
4760                                                                                         if (!editorenabled)
4761                                                                                             Person::players[i]->howactive = typeactive;
4762                                                                                     }
4763                                                                             }
4764                                                                             //jump down on player
4765                                                                             if (hostile) {
4766                                                                                 if (k == 0 && i != 0 && Person::players[k]->animTarget == jumpdownanim &&
4767                                                                                         !Person::players[i]->isCrouch() &&
4768                                                                                         Person::players[i]->animTarget != rollanim &&
4769                                                                                         !Person::players[k]->skeleton.oldfree && !
4770                                                                                         Person::players[k]->skeleton.free &&
4771                                                                                         Person::players[k]->lastcollide <= 0 &&
4772                                                                                         Person::players[k]->velocity.y < -10) {
4773                                                                                     Person::players[i]->velocity = Person::players[k]->velocity;
4774                                                                                     Person::players[k]->velocity = Person::players[k]->velocity * -.5;
4775                                                                                     Person::players[k]->velocity.y = Person::players[i]->velocity.y;
4776                                                                                     Person::players[i]->DoDamage(20);
4777                                                                                     Person::players[i]->RagDoll(0);
4778                                                                                     Person::players[k]->lastcollide = 1;
4779                                                                                     award_bonus(k, AboveBonus);
4780                                                                                 }
4781                                                                                 if (i == 0 && k != 0 && Person::players[i]->animTarget == jumpdownanim &&
4782                                                                                         !Person::players[k]->isCrouch() &&
4783                                                                                         Person::players[k]->animTarget != rollanim &&
4784                                                                                         !Person::players[i]->skeleton.oldfree &&
4785                                                                                         !Person::players[i]->skeleton.free &&
4786                                                                                         Person::players[i]->lastcollide <= 0 &&
4787                                                                                         Person::players[i]->velocity.y < -10) {
4788                                                                                     Person::players[k]->velocity = Person::players[i]->velocity;
4789                                                                                     Person::players[i]->velocity = Person::players[i]->velocity * -.3;
4790                                                                                     Person::players[i]->velocity.y = Person::players[k]->velocity.y;
4791                                                                                     Person::players[k]->DoDamage(20);
4792                                                                                     Person::players[k]->RagDoll(0);
4793                                                                                     Person::players[i]->lastcollide = 1;
4794                                                                                     award_bonus(i, AboveBonus);
4795                                                                                 }
4796                                                                             }
4797                                                                         }
4798                                                                     }
4799                                                                 }
4800                                                                 Person::players[i]->CheckKick();
4801                                                                 Person::players[k]->CheckKick();
4802                                                             }
4803                                                         }
4804             }
4805 }
4806
4807 void doAI(int i)
4808 {
4809     static bool connected;
4810     if (Person::players[i]->aitype != playercontrolled && indialogue == -1) {
4811         Person::players[i]->jumpclimb = 0;
4812         //disable movement in editor
4813         if (editorenabled)
4814             Person::players[i]->stunned = 1;
4815
4816         Person::players[i]->pause = 0;
4817         if (distsqflat(&Person::players[0]->coords, &Person::players[i]->coords) < 30 &&
4818                 Person::players[0]->coords.y > Person::players[i]->coords.y + 2 &&
4819                 !Person::players[0]->onterrain)
4820             Person::players[i]->pause = 1;
4821
4822         //pathfinding
4823         if (Person::players[i]->aitype == pathfindtype) {
4824             if (Person::players[i]->finalpathfindpoint == -1) {
4825                 float closestdistance;
4826                 float tempdist;
4827                 int closest;
4828                 XYZ colpoint;
4829                 closest = -1;
4830                 closestdistance = -1;
4831                 for (int j = 0; j < numpathpoints; j++)
4832                     if (closest == -1 || distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]) < closestdistance) {
4833                         closestdistance = distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]);
4834                         closest = j;
4835                         Person::players[i]->finaltarget = pathpoint[j];
4836                     }
4837                 Person::players[i]->finalpathfindpoint = closest;
4838                 for (int j = 0; j < numpathpoints; j++)
4839                     for (int k = 0; k < numpathpointconnect[j]; k++) {
4840                         DistancePointLine(&Person::players[i]->finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
4841                         if (sq(tempdist) < closestdistance)
4842                             if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
4843                                     findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
4844                                 closestdistance = sq(tempdist);
4845                                 closest = j;
4846                                 Person::players[i]->finaltarget = colpoint;
4847                             }
4848                     }
4849                 Person::players[i]->finalpathfindpoint = closest;
4850
4851             }
4852             if (Person::players[i]->targetpathfindpoint == -1) {
4853                 float closestdistance;
4854                 float tempdist;
4855                 int closest;
4856                 XYZ colpoint;
4857                 closest = -1;
4858                 closestdistance = -1;
4859                 if (Person::players[i]->lastpathfindpoint == -1) {
4860                     for (int j = 0; j < numpathpoints; j++) {
4861                         if (j != Person::players[i]->lastpathfindpoint)
4862                             if (closest == -1 || (distsq(&Person::players[i]->coords, &pathpoint[j]) < closestdistance)) {
4863                                 closestdistance = distsq(&Person::players[i]->coords, &pathpoint[j]);
4864                                 closest = j;
4865                             }
4866                     }
4867                     Person::players[i]->targetpathfindpoint = closest;
4868                     for (int j = 0; j < numpathpoints; j++)
4869                         if (j != Person::players[i]->lastpathfindpoint)
4870                             for (int k = 0; k < numpathpointconnect[j]; k++) {
4871                                 DistancePointLine(&Person::players[i]->coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
4872                                 if (sq(tempdist) < closestdistance) {
4873                                     if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
4874                                             findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
4875                                         closestdistance = sq(tempdist);
4876                                         closest = j;
4877                                     }
4878                                 }
4879                             }
4880                     Person::players[i]->targetpathfindpoint = closest;
4881                 } else {
4882                     for (int j = 0; j < numpathpoints; j++)
4883                         if (j != Person::players[i]->lastpathfindpoint &&
4884                                 j != Person::players[i]->lastpathfindpoint2 &&
4885                                 j != Person::players[i]->lastpathfindpoint3 &&
4886                                 j != Person::players[i]->lastpathfindpoint4) {
4887                             connected = 0;
4888                             if (numpathpointconnect[j])
4889                                 for (int k = 0; k < numpathpointconnect[j]; k++)
4890                                     if (pathpointconnect[j][k] == Person::players[i]->lastpathfindpoint)
4891                                         connected = 1;
4892                             if (!connected)
4893                                 if (numpathpointconnect[Person::players[i]->lastpathfindpoint])
4894                                     for (int k = 0; k < numpathpointconnect[Person::players[i]->lastpathfindpoint]; k++)
4895                                         if (pathpointconnect[Person::players[i]->lastpathfindpoint][k] == j)
4896                                             connected = 1;
4897                             if (connected) {
4898                                 tempdist = findPathDist(j, Person::players[i]->finalpathfindpoint);
4899                                 if (closest == -1 || tempdist < closestdistance) {
4900                                     closestdistance = tempdist;
4901                                     closest = j;
4902                                 }
4903                             }
4904                         }
4905                     Person::players[i]->targetpathfindpoint = closest;
4906                 }
4907             }
4908             Person::players[i]->losupdatedelay -= multiplier;
4909
4910             Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, pathpoint[Person::players[i]->targetpathfindpoint]);
4911             Person::players[i]->lookyaw = Person::players[i]->targetyaw;
4912
4913             //reached target point
4914             if (distsqflat(&Person::players[i]->coords, &pathpoint[Person::players[i]->targetpathfindpoint]) < .6) {
4915                 Person::players[i]->lastpathfindpoint4 = Person::players[i]->lastpathfindpoint3;
4916                 Person::players[i]->lastpathfindpoint3 = Person::players[i]->lastpathfindpoint2;
4917                 Person::players[i]->lastpathfindpoint2 = Person::players[i]->lastpathfindpoint;
4918                 Person::players[i]->lastpathfindpoint = Person::players[i]->targetpathfindpoint;
4919                 if (Person::players[i]->lastpathfindpoint2 == -1)
4920                     Person::players[i]->lastpathfindpoint2 = Person::players[i]->lastpathfindpoint;
4921                 if (Person::players[i]->lastpathfindpoint3 == -1)
4922                     Person::players[i]->lastpathfindpoint3 = Person::players[i]->lastpathfindpoint2;
4923                 if (Person::players[i]->lastpathfindpoint4 == -1)
4924                     Person::players[i]->lastpathfindpoint4 = Person::players[i]->lastpathfindpoint3;
4925                 Person::players[i]->targetpathfindpoint = -1;
4926             }
4927             if (     distsqflat(&Person::players[i]->coords, &Person::players[i]->finalfinaltarget) <
4928                      distsqflat(&Person::players[i]->coords, &Person::players[i]->finaltarget) ||
4929                      distsqflat(&Person::players[i]->coords, &Person::players[i]->finaltarget) < .6 * sq(Person::players[i]->scale * 5) ||
4930                      Person::players[i]->lastpathfindpoint == Person::players[i]->finalpathfindpoint) {
4931                 Person::players[i]->aitype = passivetype;
4932             }
4933
4934             Person::players[i]->forwardkeydown = 1;
4935             Person::players[i]->leftkeydown = 0;
4936             Person::players[i]->backkeydown = 0;
4937             Person::players[i]->rightkeydown = 0;
4938             Person::players[i]->crouchkeydown = 0;
4939             Person::players[i]->attackkeydown = 0;
4940             Person::players[i]->throwkeydown = 0;
4941
4942             if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8)
4943                 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
4944
4945             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
4946                 Person::players[i]->jumpkeydown = 0;
4947             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
4948                 Person::players[i]->jumpkeydown = 1;
4949
4950             if ((tutoriallevel != 1 || cananger) &&
4951                     hostile &&
4952                     !Person::players[0]->dead &&
4953                     distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
4954                     Person::players[i]->occluded < 25) {
4955                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
4956                         animation[Person::players[0]->animTarget].height != lowheight &&
4957                         !editorenabled &&
4958                         (Person::players[0]->coords.y < Person::players[i]->coords.y + 5 || Person::players[0]->onterrain))
4959                     Person::players[i]->aitype = attacktypecutoff;
4960                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
4961                         animation[Person::players[0]->animTarget].height == highheight &&
4962                         !editorenabled)
4963                     Person::players[i]->aitype = attacktypecutoff;
4964
4965                 if (Person::players[i]->losupdatedelay < 0 && !editorenabled && Person::players[i]->occluded < 2) {
4966                     Person::players[i]->losupdatedelay = .2;
4967                     for (int j = 0; j < numplayers; j++)
4968                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
4969                             if (abs(Random() % 2) || animation[Person::players[j]->animTarget].height != lowheight || j != 0)
4970                                 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
4971                                     if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
4972                                         if (Person::players[j]->coords.y < Person::players[i]->coords.y + 5 || Person::players[j]->onterrain)
4973                                             if (!Person::players[j]->isWallJump() && -1 == checkcollide(
4974                                                         DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)
4975                                                         *Person::players[i]->scale + Person::players[i]->coords,
4976                                                         DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
4977                                                         *Person::players[j]->scale + Person::players[j]->coords) ||
4978                                                     (Person::players[j]->animTarget == hanganim &&
4979                                                      normaldotproduct(Person::players[j]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0)) {
4980                                                 Person::players[i]->aitype = searchtype;
4981                                                 Person::players[i]->lastchecktime = 12;
4982                                                 Person::players[i]->lastseen = Person::players[j]->coords;
4983                                                 Person::players[i]->lastseentime = 12;
4984                                             }
4985                 }
4986             }
4987             if (Person::players[i]->aitype == attacktypecutoff && musictype != 2)
4988                 if (Person::players[i]->creature != wolftype) {
4989                     Person::players[i]->stunned = .6;
4990                     Person::players[i]->surprised = .6;
4991                 }
4992         }
4993
4994         if (Person::players[i]->aitype != passivetype && leveltime > .5)
4995             Person::players[i]->howactive = typeactive;
4996
4997         if (Person::players[i]->aitype == passivetype) {
4998             Person::players[i]->aiupdatedelay -= multiplier;
4999             Person::players[i]->losupdatedelay -= multiplier;
5000             Person::players[i]->lastseentime += multiplier;
5001             Person::players[i]->pausetime -= multiplier;
5002             if (Person::players[i]->lastseentime > 1)
5003                 Person::players[i]->lastseentime = 1;
5004
5005             if (Person::players[i]->aiupdatedelay < 0) {
5006                 if (Person::players[i]->numwaypoints > 1 && Person::players[i]->howactive == typeactive && Person::players[i]->pausetime <= 0) {
5007                     Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[i]->waypoints[Person::players[i]->waypoint]);
5008                     Person::players[i]->lookyaw = Person::players[i]->targetyaw;
5009                     Person::players[i]->aiupdatedelay = .05;
5010
5011                     if (distsqflat(&Person::players[i]->coords, &Person::players[i]->waypoints[Person::players[i]->waypoint]) < 1) {
5012                         if (Person::players[i]->waypointtype[Person::players[i]->waypoint] == wppause)
5013                             Person::players[i]->pausetime = 4;
5014                         Person::players[i]->waypoint++;
5015                         if (Person::players[i]->waypoint > Person::players[i]->numwaypoints - 1)
5016                             Person::players[i]->waypoint = 0;
5017
5018                     }
5019                 }
5020
5021                 if (Person::players[i]->numwaypoints > 1 && Person::players[i]->howactive == typeactive && Person::players[i]->pausetime <= 0)
5022                     Person::players[i]->forwardkeydown = 1;
5023                 else
5024                     Person::players[i]->forwardkeydown = 0;
5025                 Person::players[i]->leftkeydown = 0;
5026                 Person::players[i]->backkeydown = 0;
5027                 Person::players[i]->rightkeydown = 0;
5028                 Person::players[i]->crouchkeydown = 0;
5029                 Person::players[i]->attackkeydown = 0;
5030                 Person::players[i]->throwkeydown = 0;
5031
5032                 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
5033                     if (!Person::players[i]->avoidsomething)
5034                         Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
5035                     else {
5036                         XYZ leftpos, rightpos;
5037                         float leftdist, rightdist;
5038                         leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
5039                         rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
5040                         leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
5041                         rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
5042                         if (leftdist < rightdist)
5043                             Person::players[i]->targetyaw += 90;
5044                         else
5045                             Person::players[i]->targetyaw -= 90;
5046                     }
5047                 }
5048             }
5049             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
5050                 Person::players[i]->jumpkeydown = 0;
5051             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
5052                 Person::players[i]->jumpkeydown = 1;
5053
5054
5055             //hearing sounds
5056             if (!editorenabled) {
5057                 if (Person::players[i]->howactive <= typesleeping)
5058                     if (numenvsounds > 0 && (tutoriallevel != 1 || cananger) && hostile)
5059                         for (int j = 0; j < numenvsounds; j++) {
5060                             float vol = Person::players[i]->howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
5061                             if (vol > 0 && distsq(&Person::players[i]->coords, &envsound[j]) <
5062                                     2 * (vol + vol * (Person::players[i]->creature == rabbittype) * 3))
5063                                 Person::players[i]->aitype = attacktypecutoff;
5064                         }
5065
5066                 if (Person::players[i]->aitype != passivetype) {
5067                     if (Person::players[i]->howactive == typesleeping)
5068                         Person::players[i]->setAnimation(getupfromfrontanim);
5069                     Person::players[i]->howactive = typeactive;
5070                 }
5071             }
5072
5073             if (Person::players[i]->howactive < typesleeping &&
5074                     ((tutoriallevel != 1 || cananger) && hostile) &&
5075                     !Person::players[0]->dead &&
5076                     distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
5077                     Person::players[i]->occluded < 25) {
5078                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
5079                         animation[Person::players[0]->animTarget].height != lowheight && !editorenabled)
5080                     Person::players[i]->aitype = attacktypecutoff;
5081                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
5082                         animation[Person::players[0]->animTarget].height == highheight && !editorenabled)
5083                     Person::players[i]->aitype = attacktypecutoff;
5084
5085                 //wolf smell
5086                 if (Person::players[i]->creature == wolftype) {
5087                     XYZ windsmell;
5088                     for (int j = 0; j < numplayers; j++) {
5089                         if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
5090                             float smelldistance = 50;
5091                             if (j == 0 && Person::players[j]->num_weapons > 0) {
5092                                 if (weapons[Person::players[j]->weaponids[0]].bloody)
5093                                     smelldistance = 100;
5094                                 if (Person::players[j]->num_weapons == 2)
5095                                     if (weapons[Person::players[j]->weaponids[1]].bloody)
5096                                         smelldistance = 100;
5097                             }
5098                             if (j != 0)
5099                                 smelldistance = 100;
5100                             windsmell = windvector;
5101                             Normalise(&windsmell);
5102                             windsmell = windsmell * 2 + Person::players[j]->coords;
5103                             if (distsq(&Person::players[i]->coords, &windsmell) < smelldistance && !editorenabled)
5104                                 Person::players[i]->aitype = attacktypecutoff;
5105                         }
5106                     }
5107                 }
5108
5109                 if (Person::players[i]->howactive < typesleeping && Person::players[i]->losupdatedelay < 0 && !editorenabled && Person::players[i]->occluded < 2) {
5110                     Person::players[i]->losupdatedelay = .2;
5111                     for (int j = 0; j < numplayers; j++) {
5112                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
5113                             if (abs(Random() % 2) || animation[Person::players[j]->animTarget].height != lowheight || j != 0)
5114                                 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
5115                                     if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
5116                                         if ((-1 == checkcollide(
5117                                                     DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)*
5118                                                     Person::players[i]->scale + Person::players[i]->coords,
5119                                                     DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
5120                                                     Person::players[j]->scale + Person::players[j]->coords) &&
5121                                                 !Person::players[j]->isWallJump()) ||
5122                                                 (Person::players[j]->animTarget == hanganim &&
5123                                                  normaldotproduct(Person::players[j]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0)) {
5124                                             Person::players[i]->lastseentime -= .2;
5125                                             if (j == 0 && animation[Person::players[j]->animTarget].height == lowheight)
5126                                                 Person::players[i]->lastseentime -= .4;
5127                                             else
5128                                                 Person::players[i]->lastseentime -= .6;
5129                                         }
5130                             if (Person::players[i]->lastseentime <= 0) {
5131                                 Person::players[i]->aitype = searchtype;
5132                                 Person::players[i]->lastchecktime = 12;
5133                                 Person::players[i]->lastseen = Person::players[j]->coords;
5134                                 Person::players[i]->lastseentime = 12;
5135                             }
5136                         }
5137                     }
5138                 }
5139             }
5140             //alerted surprise
5141             if (Person::players[i]->aitype == attacktypecutoff && musictype != 2) {
5142                 if (Person::players[i]->creature != wolftype) {
5143                     Person::players[i]->stunned = .6;
5144                     Person::players[i]->surprised = .6;
5145                 }
5146                 if (Person::players[i]->creature == wolftype) {
5147                     Person::players[i]->stunned = .47;
5148                     Person::players[i]->surprised = .47;
5149                 }
5150                 numseen++;
5151             }
5152         }
5153
5154         //search for player
5155         int j;
5156         if (Person::players[i]->aitype == searchtype) {
5157             Person::players[i]->aiupdatedelay -= multiplier;
5158             Person::players[i]->losupdatedelay -= multiplier;
5159             if (!Person::players[i]->pause)
5160                 Person::players[i]->lastseentime -= multiplier;
5161             Person::players[i]->lastchecktime -= multiplier;
5162
5163             if (Person::players[i]->isRun() && !Person::players[i]->onground) {
5164                 if (Person::players[i]->coords.y > terrain.getHeight(Person::players[i]->coords.x, Person::players[i]->coords.z) + 10) {
5165                     XYZ test2 = Person::players[i]->coords + Person::players[i]->facing;
5166                     test2.y += 5;
5167                     XYZ test = Person::players[i]->coords + Person::players[i]->facing;
5168                     test.y -= 10;
5169                     j = checkcollide(test2, test, Person::players[i]->laststanding);
5170                     if (j == -1)
5171                         j = checkcollide(test2, test);
5172                     if (j == -1) {
5173                         Person::players[i]->velocity = 0;
5174                         Person::players[i]->setAnimation(Person::players[i]->getStop());
5175                         Person::players[i]->targetyaw += 180;
5176                         Person::players[i]->stunned = .5;
5177                         //Person::players[i]->aitype=passivetype;
5178                         Person::players[i]->aitype = pathfindtype;
5179                         Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
5180                         Person::players[i]->finalpathfindpoint = -1;
5181                         Person::players[i]->targetpathfindpoint = -1;
5182                         Person::players[i]->lastpathfindpoint = -1;
5183                         Person::players[i]->lastpathfindpoint2 = -1;
5184                         Person::players[i]->lastpathfindpoint3 = -1;
5185                         Person::players[i]->lastpathfindpoint4 = -1;
5186                     } else
5187                         Person::players[i]->laststanding = j;
5188                 }
5189             }
5190             //check out last seen location
5191             if (Person::players[i]->aiupdatedelay < 0) {
5192                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[i]->lastseen);
5193                 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
5194                 Person::players[i]->aiupdatedelay = .05;
5195                 Person::players[i]->forwardkeydown = 1;
5196
5197                 if (distsqflat(&Person::players[i]->coords, &Person::players[i]->lastseen) < 1 * sq(Person::players[i]->scale * 5) || Person::players[i]->lastchecktime < 0) {
5198                     Person::players[i]->forwardkeydown = 0;
5199                     Person::players[i]->aiupdatedelay = 1;
5200                     Person::players[i]->lastseen.x += (float(Random() % 100) - 50) / 25;
5201                     Person::players[i]->lastseen.z += (float(Random() % 100) - 50) / 25;
5202                     Person::players[i]->lastchecktime = 3;
5203                 }
5204
5205                 Person::players[i]->leftkeydown = 0;
5206                 Person::players[i]->backkeydown = 0;
5207                 Person::players[i]->rightkeydown = 0;
5208                 Person::players[i]->crouchkeydown = 0;
5209                 Person::players[i]->attackkeydown = 0;
5210                 Person::players[i]->throwkeydown = 0;
5211
5212                 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
5213                     if (!Person::players[i]->avoidsomething)
5214                         Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
5215                     else {
5216                         XYZ leftpos, rightpos;
5217                         float leftdist, rightdist;
5218                         leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
5219                         rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
5220                         leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
5221                         rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
5222                         if (leftdist < rightdist)
5223                             Person::players[i]->targetyaw += 90;
5224                         else
5225                             Person::players[i]->targetyaw -= 90;
5226                     }
5227                 }
5228             }
5229             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
5230                 Person::players[i]->jumpkeydown = 0;
5231             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
5232                 Person::players[i]->jumpkeydown = 1;
5233
5234             if (numenvsounds > 0 && ((tutoriallevel != 1 || cananger) && hostile))
5235                 for (int k = 0; k < numenvsounds; k++) {
5236                     if (distsq(&Person::players[i]->coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (Person::players[i]->creature == rabbittype) * 3)) {
5237                         Person::players[i]->aitype = attacktypecutoff;
5238                     }
5239                 }
5240
5241             if (!Person::players[0]->dead &&
5242                     Person::players[i]->losupdatedelay < 0 &&
5243                     !editorenabled &&
5244                     Person::players[i]->occluded < 2 &&
5245                     ((tutoriallevel != 1 || cananger) && hostile)) {
5246                 Person::players[i]->losupdatedelay = .2;
5247                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 4 && animation[Person::players[i]->animTarget].height != lowheight) {
5248                     Person::players[i]->aitype = attacktypecutoff;
5249                     Person::players[i]->lastseentime = 1;
5250                 }
5251                 if (abs(Random() % 2) || animation[Person::players[i]->animTarget].height != lowheight)
5252                     //TODO: factor out canSeePlayer()
5253                     if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400)
5254                         if (normaldotproduct(Person::players[i]->facing, Person::players[0]->coords - Person::players[i]->coords) > 0)
5255                             if ((checkcollide(
5256                                         DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)*
5257                                         Person::players[i]->scale + Person::players[i]->coords,
5258                                         DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
5259                                         Person::players[0]->scale + Person::players[0]->coords) == -1) ||
5260                                     (Person::players[0]->animTarget == hanganim && normaldotproduct(
5261                                          Person::players[0]->facing, Person::players[i]->coords - Person::players[0]->coords) < 0)) {
5262                                 /* //TODO: changed j to 0 on a whim, make sure this is correct
5263                                 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
5264                                     Person::players[j]->facing,Person::players[i]->coords-Person::players[j]->coords)<0)
5265                                 */
5266                                 Person::players[i]->aitype = attacktypecutoff;
5267                                 Person::players[i]->lastseentime = 1;
5268                             }
5269             }
5270             //player escaped
5271             if (Person::players[i]->lastseentime < 0) {
5272                 //Person::players[i]->aitype=passivetype;
5273                 numescaped++;
5274                 Person::players[i]->aitype = pathfindtype;
5275                 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
5276                 Person::players[i]->finalpathfindpoint = -1;
5277                 Person::players[i]->targetpathfindpoint = -1;
5278                 Person::players[i]->lastpathfindpoint = -1;
5279                 Person::players[i]->lastpathfindpoint2 = -1;
5280                 Person::players[i]->lastpathfindpoint3 = -1;
5281                 Person::players[i]->lastpathfindpoint4 = -1;
5282             }
5283         }
5284
5285         if (Person::players[i]->aitype != gethelptype)
5286             Person::players[i]->runninghowlong = 0;
5287
5288         //get help from buddies
5289         if (Person::players[i]->aitype == gethelptype) {
5290             Person::players[i]->runninghowlong += multiplier;
5291             Person::players[i]->aiupdatedelay -= multiplier;
5292
5293             if (Person::players[i]->aiupdatedelay < 0 || Person::players[i]->ally == 0) {
5294                 Person::players[i]->aiupdatedelay = .2;
5295
5296                 //find closest ally
5297                 //TODO: factor out closest search somehow
5298                 if (!Person::players[i]->ally) {
5299                     int closest = -1;
5300                     float closestdist = -1;
5301                     for (int k = 0; k < numplayers; k++) {
5302                         if (k != i && k != 0 && !Person::players[k]->dead &&
5303                                 Person::players[k]->howactive < typedead1 &&
5304                                 !Person::players[k]->skeleton.free &&
5305                                 Person::players[k]->aitype == passivetype) {
5306                             float distance = distsq(&Person::players[i]->coords, &Person::players[k]->coords);
5307                             if (closestdist == -1 || distance < closestdist) {
5308                                 closestdist = distance;
5309                                 closest = k;
5310                             }
5311                             closest = k;
5312                         }
5313                     }
5314                     if (closest != -1)
5315                         Person::players[i]->ally = closest;
5316                     else
5317                         Person::players[i]->ally = 0;
5318                     Person::players[i]->lastseen = Person::players[0]->coords;
5319                     Person::players[i]->lastseentime = 12;
5320                 }
5321
5322
5323                 Person::players[i]->lastchecktime = 12;
5324
5325                 XYZ facing = Person::players[i]->coords;
5326                 XYZ flatfacing = Person::players[Person::players[i]->ally]->coords;
5327                 facing.y += Person::players[i]->jointPos(head).y * Person::players[i]->scale;
5328                 flatfacing.y += Person::players[Person::players[i]->ally]->jointPos(head).y * Person::players[Person::players[i]->ally]->scale;
5329                 if (-1 != checkcollide(facing, flatfacing))
5330                     Person::players[i]->lastseentime -= .1;
5331
5332                 //no available ally, run back to player
5333                 if (Person::players[i]->ally <= 0 ||
5334                         Person::players[Person::players[i]->ally]->skeleton.free ||
5335                         Person::players[Person::players[i]->ally]->aitype != passivetype ||
5336                         Person::players[i]->lastseentime <= 0) {
5337                     Person::players[i]->aitype = searchtype;
5338                     Person::players[i]->lastseentime = 12;
5339                 }
5340
5341                 //seek out ally
5342                 if (Person::players[i]->ally > 0) {
5343                     Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[Person::players[i]->ally]->coords);
5344                     Person::players[i]->lookyaw = Person::players[i]->targetyaw;
5345                     Person::players[i]->aiupdatedelay = .05;
5346                     Person::players[i]->forwardkeydown = 1;
5347
5348                     if (distsqflat(&Person::players[i]->coords, &Person::players[Person::players[i]->ally]->coords) < 3) {
5349                         Person::players[i]->aitype = searchtype;
5350                         Person::players[i]->lastseentime = 12;
5351                         Person::players[Person::players[i]->ally]->aitype = searchtype;
5352                         if (Person::players[Person::players[i]->ally]->lastseentime < Person::players[i]->lastseentime) {
5353                             Person::players[Person::players[i]->ally]->lastseen = Person::players[i]->lastseen;
5354                             Person::players[Person::players[i]->ally]->lastseentime = Person::players[i]->lastseentime;
5355                             Person::players[Person::players[i]->ally]->lastchecktime = Person::players[i]->lastchecktime;
5356                         }
5357                     }
5358
5359                     if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
5360                         if (!Person::players[i]->avoidsomething)
5361                             Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
5362                         else {
5363                             XYZ leftpos, rightpos;
5364                             float leftdist, rightdist;
5365                             leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
5366                             rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
5367                             leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
5368                             rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
5369                             if (leftdist < rightdist)
5370                                 Person::players[i]->targetyaw += 90;
5371                             else
5372                                 Person::players[i]->targetyaw -= 90;
5373                         }
5374                     }
5375                 }
5376
5377                 Person::players[i]->leftkeydown = 0;
5378                 Person::players[i]->backkeydown = 0;
5379                 Person::players[i]->rightkeydown = 0;
5380                 Person::players[i]->crouchkeydown = 0;
5381                 Person::players[i]->attackkeydown = 0;
5382             }
5383             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
5384                 Person::players[i]->jumpkeydown = 0;
5385             if (Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5)
5386                 Person::players[i]->jumpkeydown = 1;
5387         }
5388
5389         //retreiving a weapon on the ground
5390         if (Person::players[i]->aitype == getweapontype) {
5391             Person::players[i]->aiupdatedelay -= multiplier;
5392             Person::players[i]->lastchecktime -= multiplier;
5393
5394             if (Person::players[i]->aiupdatedelay < 0) {
5395                 Person::players[i]->aiupdatedelay = .2;
5396
5397                 //ALLY IS WEPON
5398                 if (Person::players[i]->ally < 0) {
5399                     int closest = -1;
5400                     float closestdist = -1;
5401                     for (int k = 0; k < weapons.size(); k++)
5402                         if (weapons[k].owner == -1) {
5403                             float distance = distsq(&Person::players[i]->coords, &weapons[k].position);
5404                             if (closestdist == -1 || distance < closestdist) {
5405                                 closestdist = distance;
5406                                 closest = k;
5407                             }
5408                             closest = k;
5409                         }
5410                     if (closest != -1)
5411                         Person::players[i]->ally = closest;
5412                     else
5413                         Person::players[i]->ally = -1;
5414                 }
5415
5416                 Person::players[i]->lastseentime = 12;
5417
5418                 if (!Person::players[0]->dead && ((tutoriallevel != 1 || cananger) && hostile))
5419                     if (Person::players[i]->ally < 0 || Person::players[i]->weaponactive != -1 || Person::players[i]->lastchecktime <= 0) {
5420                         Person::players[i]->aitype = attacktypecutoff;
5421                         Person::players[i]->lastseentime = 1;
5422                     }
5423                 if (!Person::players[0]->dead)
5424                     if (Person::players[i]->ally >= 0) {
5425                         if (weapons[Person::players[i]->ally].owner != -1 ||
5426                                 distsq(&Person::players[i]->coords, &weapons[Person::players[i]->ally].position) > 16) {
5427                             Person::players[i]->aitype = attacktypecutoff;
5428                             Person::players[i]->lastseentime = 1;
5429                         }
5430                         //TODO: factor these out as moveToward()
5431                         Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[Person::players[i]->ally].position);
5432                         Person::players[i]->lookyaw = Person::players[i]->targetyaw;
5433                         Person::players[i]->aiupdatedelay = .05;
5434                         Person::players[i]->forwardkeydown = 1;
5435
5436
5437                         if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
5438                             if (!Person::players[i]->avoidsomething)
5439                                 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
5440                             else {
5441                                 XYZ leftpos, rightpos;
5442                                 float leftdist, rightdist;
5443                                 leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
5444                                 rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
5445                                 leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
5446                                 rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
5447                                 if (leftdist < rightdist)
5448                                     Person::players[i]->targetyaw += 90;
5449                                 else
5450                                     Person::players[i]->targetyaw -= 90;
5451                             }
5452                         }
5453                     }
5454
5455                 Person::players[i]->leftkeydown = 0;
5456                 Person::players[i]->backkeydown = 0;
5457                 Person::players[i]->rightkeydown = 0;
5458                 Person::players[i]->attackkeydown = 0;
5459                 Person::players[i]->throwkeydown = 1;
5460                 Person::players[i]->crouchkeydown = 0;
5461                 if (Person::players[i]->animTarget != crouchremoveknifeanim &&
5462                         Person::players[i]->animTarget != removeknifeanim)
5463                     Person::players[i]->throwtogglekeydown = 0;
5464                 Person::players[i]->drawkeydown = 0;
5465             }
5466             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
5467                 Person::players[i]->jumpkeydown = 0;
5468             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
5469                 Person::players[i]->jumpkeydown = 1;
5470         }
5471
5472         if (Person::players[i]->aitype == attacktypecutoff) {
5473             Person::players[i]->aiupdatedelay -= multiplier;
5474             //dodge or reverse rabbit kicks, knife throws, flips
5475             if (Person::players[i]->damage < Person::players[i]->damagetolerance * 2 / 3)
5476                 if ((Person::players[0]->animTarget == rabbitkickanim ||
5477                         Person::players[0]->animTarget == knifethrowanim ||
5478                         (Person::players[0]->isFlip() &&
5479                          normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - Person::players[i]->coords) < 0)) &&
5480                         !Person::players[0]->skeleton.free &&
5481                         (Person::players[i]->aiupdatedelay < .1)) {
5482                     Person::players[i]->attackkeydown = 0;
5483                     if (Person::players[i]->isIdle())
5484                         Person::players[i]->crouchkeydown = 1;
5485                     if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
5486                         if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
5487                             if (Person::players[i]->isIdle() || Person::players[i]->isCrouch() || Person::players[i]->isRun() || Person::players[i]->isFlip()) {
5488                                 if (abs(Random() % 2 == 0))
5489                                     Person::players[i]->setAnimation(backhandspringanim);
5490                                 else
5491                                     Person::players[i]->setAnimation(rollanim);
5492                                 Person::players[i]->targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
5493                                 Person::players[i]->wentforweapon = 0;
5494                             }
5495                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim)
5496                                 Person::players[i]->setAnimation(flipanim);
5497                         }
5498                     }
5499                     Person::players[i]->forwardkeydown = 0;
5500                     Person::players[i]->aiupdatedelay = .02;
5501                 }
5502             //get confused by flips
5503             if (Person::players[0]->isFlip() &&
5504                     !Person::players[0]->skeleton.free &&
5505                     Person::players[0]->animTarget != walljumprightkickanim &&
5506                     Person::players[0]->animTarget != walljumpleftkickanim) {
5507                 if (distsq(&Person::players[0]->coords, &Person::players[i]->coords) < 25)
5508                     if ((1 - Person::players[i]->damage / Person::players[i]->damagetolerance) > .5)
5509                         Person::players[i]->stunned = 1;
5510             }
5511             //go for weapon on the ground
5512             if (Person::players[i]->wentforweapon < 3)
5513                 for (int k = 0; k < weapons.size(); k++)
5514                     if (Person::players[i]->creature != wolftype)
5515                         if (Person::players[i]->num_weapons == 0 &&
5516                                 weapons[k].owner == -1 &&
5517                                 weapons[i].velocity.x == 0 &&
5518                                 weapons[i].velocity.z == 0 &&
5519                                 weapons[i].velocity.y == 0) {
5520                             if (distsq(&Person::players[i]->coords, &weapons[k].position) < 16) {
5521                                 Person::players[i]->wentforweapon++;
5522                                 Person::players[i]->lastchecktime = 6;
5523                                 Person::players[i]->aitype = getweapontype;
5524                                 Person::players[i]->ally = -1;
5525                             }
5526                         }
5527             //dodge/reverse walljump kicks
5528             if (Person::players[i]->damage < Person::players[i]->damagetolerance / 2)
5529                 if (animation[Person::players[i]->animTarget].height != highheight)
5530                     if (Person::players[i]->damage < Person::players[i]->damagetolerance * .5 &&
5531                             ((Person::players[0]->animTarget == walljumprightkickanim ||
5532                               Person::players[0]->animTarget == walljumpleftkickanim) &&
5533                              ((Person::players[i]->aiupdatedelay < .15 &&
5534                                difficulty == 2) ||
5535                               (Person::players[i]->aiupdatedelay < .08 &&
5536                                difficulty != 2)))) {
5537                         Person::players[i]->crouchkeydown = 1;
5538                     }
5539             //walked off a ledge (?)
5540             if (Person::players[i]->isRun() && !Person::players[i]->onground)
5541                 if (Person::players[i]->coords.y > terrain.getHeight(Person::players[i]->coords.x, Person::players[i]->coords.z) + 10) {
5542                     XYZ test2 = Person::players[i]->coords + Person::players[i]->facing;
5543                     test2.y += 5;
5544                     XYZ test = Person::players[i]->coords + Person::players[i]->facing;
5545                     test.y -= 10;
5546                     j = checkcollide(test2, test, Person::players[i]->laststanding);
5547                     if (j == -1)
5548                         j = checkcollide(test2, test);
5549                     if (j == -1) {
5550                         Person::players[i]->velocity = 0;
5551                         Person::players[i]->setAnimation(Person::players[i]->getStop());
5552                         Person::players[i]->targetyaw += 180;
5553                         Person::players[i]->stunned = .5;
5554                         Person::players[i]->aitype = pathfindtype;
5555                         Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
5556                         Person::players[i]->finalpathfindpoint = -1;
5557                         Person::players[i]->targetpathfindpoint = -1;
5558                         Person::players[i]->lastpathfindpoint = -1;
5559                         Person::players[i]->lastpathfindpoint2 = -1;
5560                         Person::players[i]->lastpathfindpoint3 = -1;
5561                         Person::players[i]->lastpathfindpoint4 = -1;
5562                     } else
5563                         Person::players[i]->laststanding = j;
5564                 }
5565             //lose sight of player in the air (?)
5566             if (Person::players[0]->coords.y > Person::players[i]->coords.y + 5 &&
5567                     animation[Person::players[0]->animTarget].height != highheight &&
5568                     !Person::players[0]->onterrain) {
5569                 Person::players[i]->aitype = pathfindtype;
5570                 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
5571                 Person::players[i]->finalpathfindpoint = -1;
5572                 Person::players[i]->targetpathfindpoint = -1;
5573                 Person::players[i]->lastpathfindpoint = -1;
5574                 Person::players[i]->lastpathfindpoint2 = -1;
5575                 Person::players[i]->lastpathfindpoint3 = -1;
5576                 Person::players[i]->lastpathfindpoint4 = -1;
5577             }
5578             //it's time to think (?)
5579             if (Person::players[i]->aiupdatedelay < 0 &&
5580                     !animation[Person::players[i]->animTarget].attack &&
5581                     Person::players[i]->animTarget != staggerbackhighanim &&
5582                     Person::players[i]->animTarget != staggerbackhardanim &&
5583                     Person::players[i]->animTarget != backhandspringanim &&
5584                     Person::players[i]->animTarget != dodgebackanim) {
5585                 //draw weapon
5586                 if (Person::players[i]->weaponactive == -1 && Person::players[i]->num_weapons > 0)
5587                     Person::players[i]->drawkeydown = Random() % 2;
5588                 else
5589                     Person::players[i]->drawkeydown = 0;
5590                 Person::players[i]->rabbitkickenabled = Random() % 2;
5591                 //chase player
5592                 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
5593                 XYZ targetpoint = Person::players[0]->coords;
5594                 if (distsq(&Person::players[0]->coords, &Person::players[i]->coords) <
5595                         distsq(&rotatetarget, &Person::players[i]->coords))
5596                     targetpoint += Person::players[0]->velocity *
5597                                    findDistance(&Person::players[0]->coords, &Person::players[i]->coords) / findLength(&Person::players[i]->velocity);
5598                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, targetpoint);
5599                 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
5600                 Person::players[i]->aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
5601
5602                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || Person::players[i]->weaponactive != -1))
5603                     Person::players[i]->forwardkeydown = 1;
5604                 else if ((distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 16 ||
5605                           distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 9) &&
5606                          Person::players[0]->weaponactive != -1)
5607                     Person::players[i]->forwardkeydown = 1;
5608                 else if (Random() % 6 == 0 || (Person::players[i]->creature == wolftype && Random() % 3 == 0))
5609                     Person::players[i]->forwardkeydown = 1;
5610                 else
5611                     Person::players[i]->forwardkeydown = 0;
5612                 //chill out around the corpse
5613                 if (Person::players[0]->dead) {
5614                     Person::players[i]->forwardkeydown = 0;
5615                     if (Random() % 10 == 0)
5616                         Person::players[i]->forwardkeydown = 1;
5617                     if (Random() % 100 == 0) {
5618                         Person::players[i]->aitype = pathfindtype;
5619                         Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
5620                         Person::players[i]->finalpathfindpoint = -1;
5621                         Person::players[i]->targetpathfindpoint = -1;
5622                         Person::players[i]->lastpathfindpoint = -1;
5623                         Person::players[i]->lastpathfindpoint2 = -1;
5624                         Person::players[i]->lastpathfindpoint3 = -1;
5625                         Person::players[i]->lastpathfindpoint4 = -1;
5626                     }
5627                 }
5628                 Person::players[i]->leftkeydown = 0;
5629                 Person::players[i]->backkeydown = 0;
5630                 Person::players[i]->rightkeydown = 0;
5631                 Person::players[i]->crouchkeydown = 0;
5632                 Person::players[i]->throwkeydown = 0;
5633
5634                 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8)
5635                     Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
5636                 //attack!!!
5637                 if (Random() % 2 == 0 || Person::players[i]->weaponactive != -1 || Person::players[i]->creature == wolftype)
5638                     Person::players[i]->attackkeydown = 1;
5639                 else
5640                     Person::players[i]->attackkeydown = 0;
5641                 if (Person::players[i]->isRun() && Random() % 6 && distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 7)
5642                     Person::players[i]->attackkeydown = 0;
5643
5644                 //TODO: wat
5645                 if (Person::players[i]->aitype != playercontrolled &&
5646                         (Person::players[i]->isIdle() ||
5647                          Person::players[i]->isCrouch() ||
5648                          Person::players[i]->isRun())) {
5649                     int target = -2;
5650                     for (int j = 0; j < numplayers; j++)
5651                         if (j != i && !Person::players[j]->skeleton.free &&
5652                                 Person::players[j]->hasvictim &&
5653                                 (tutoriallevel == 1 && reversaltrain ||
5654                                  Random() % 2 == 0 && difficulty == 2 ||
5655                                  Random() % 4 == 0 && difficulty == 1 ||
5656                                  Random() % 8 == 0 && difficulty == 0 ||
5657                                  Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
5658                                  Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
5659                                  (Random() % 2 == 0 || difficulty == 2) ||
5660                                  (Person::players[i]->isIdle() || Person::players[i]->isRun()) &&
5661                                  Person::players[j]->weaponactive != -1 ||
5662                                  Person::players[j]->animTarget == swordslashanim &&
5663                                  Person::players[i]->weaponactive != -1 ||
5664                                  Person::players[j]->animTarget == staffhitanim ||
5665                                  Person::players[j]->animTarget == staffspinhitanim))
5666                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
5667                                     Person::players[j]->victim == Person::players[i] &&
5668                                     (Person::players[j]->animTarget == sweepanim ||
5669                                      Person::players[j]->animTarget == spinkickanim ||
5670                                      Person::players[j]->animTarget == staffhitanim ||
5671                                      Person::players[j]->animTarget == staffspinhitanim ||
5672                                      Person::players[j]->animTarget == winduppunchanim ||
5673                                      Person::players[j]->animTarget == upunchanim ||
5674                                      Person::players[j]->animTarget == wolfslapanim ||
5675                                      Person::players[j]->animTarget == knifeslashstartanim ||
5676                                      Person::players[j]->animTarget == swordslashanim &&
5677                                      (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2 ||
5678                                       Person::players[i]->weaponactive != -1))) {
5679                                 if (target >= 0)
5680                                     target = -1;
5681                                 else
5682                                     target = j;
5683                             }
5684                     if (target >= 0)
5685                         Person::players[target]->Reverse();
5686                 }
5687
5688                 if (Person::players[i]->collided < 1)
5689                     Person::players[i]->jumpkeydown = 0;
5690                 if (Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5 ||
5691                         distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 400 &&
5692                         Person::players[i]->onterrain &&
5693                         Person::players[i]->creature == rabbittype)
5694                     Person::players[i]->jumpkeydown = 1;
5695                 //TODO: why are we controlling the human?
5696                 if (normaldotproduct(Person::players[i]->facing, Person::players[0]->coords - Person::players[i]->coords) > 0)
5697                     Person::players[0]->jumpkeydown = 0;
5698                 if (Person::players[0]->animTarget == jumpdownanim &&
5699                         distsq(&Person::players[0]->coords, &Person::players[i]->coords) < 40)
5700                     Person::players[i]->crouchkeydown = 1;
5701                 if (Person::players[i]->jumpkeydown)
5702                     Person::players[i]->attackkeydown = 0;
5703
5704                 if (tutoriallevel == 1)
5705                     if (!canattack)
5706                         Person::players[i]->attackkeydown = 0;
5707
5708
5709                 XYZ facing = Person::players[i]->coords;
5710                 XYZ flatfacing = Person::players[0]->coords;
5711                 facing.y += Person::players[i]->jointPos(head).y * Person::players[i]->scale;
5712                 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
5713                 if (Person::players[i]->occluded >= 2)
5714                     if (-1 != checkcollide(facing, flatfacing)) {
5715                         if (!Person::players[i]->pause)
5716                             Person::players[i]->lastseentime -= .2;
5717                         if (Person::players[i]->lastseentime <= 0 &&
5718                                 (Person::players[i]->creature != wolftype ||
5719                                  Person::players[i]->weaponstuck == -1)) {
5720                             Person::players[i]->aitype = searchtype;
5721                             Person::players[i]->lastchecktime = 12;
5722                             Person::players[i]->lastseen = Person::players[0]->coords;
5723                             Person::players[i]->lastseentime = 12;
5724                         }
5725                     } else
5726                         Person::players[i]->lastseentime = 1;
5727             }
5728         }
5729         if (animation[Person::players[0]->animTarget].height == highheight &&
5730                 (Person::players[i]->aitype == attacktypecutoff ||
5731                  Person::players[i]->aitype == searchtype))
5732             if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
5733                 XYZ test = Person::players[0]->coords;
5734                 test.y -= 40;
5735                 if (-1 == checkcollide(Person::players[0]->coords, test))
5736                     Person::players[i]->stunned = 1;
5737             }
5738         //stunned
5739         if (Person::players[i]->aitype == passivetype && !(Person::players[i]->numwaypoints > 1) ||
5740                 Person::players[i]->stunned > 0 ||
5741                 Person::players[i]->pause && Person::players[i]->damage > Person::players[i]->superpermanentdamage) {
5742             if (Person::players[i]->pause)
5743                 Person::players[i]->lastseentime = 1;
5744             Person::players[i]->targetyaw = Person::players[i]->yaw;
5745             Person::players[i]->forwardkeydown = 0;
5746             Person::players[i]->leftkeydown = 0;
5747             Person::players[i]->backkeydown = 0;
5748             Person::players[i]->rightkeydown = 0;
5749             Person::players[i]->jumpkeydown = 0;
5750             Person::players[i]->attackkeydown = 0;
5751             Person::players[i]->crouchkeydown = 0;
5752             Person::players[i]->throwkeydown = 0;
5753         }
5754
5755
5756         XYZ facing;
5757         facing = 0;
5758         facing.z = -1;
5759
5760         XYZ flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
5761         facing = flatfacing;
5762
5763         if (Person::players[i]->aitype == attacktypecutoff) {
5764             Person::players[i]->targetheadyaw = 180 - roughDirectionTo(Person::players[i]->coords, Person::players[0]->coords);
5765             Person::players[i]->targetheadpitch = pitchTo(Person::players[i]->coords, Person::players[0]->coords);
5766         } else if (Person::players[i]->howactive >= typesleeping) {
5767             Person::players[i]->targetheadyaw = Person::players[i]->targetyaw;
5768             Person::players[i]->targetheadpitch = 0;
5769         } else {
5770             if (Person::players[i]->interestdelay <= 0) {
5771                 Person::players[i]->interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
5772                 Person::players[i]->headtarget = Person::players[i]->coords;
5773                 Person::players[i]->headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
5774                 Person::players[i]->headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
5775                 Person::players[i]->headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
5776                 Person::players[i]->headtarget += Person::players[i]->facing * 1.5;
5777             }
5778             Person::players[i]->targetheadyaw = 180 - roughDirectionTo(Person::players[i]->coords, Person::players[i]->headtarget);
5779             Person::players[i]->targetheadpitch = pitchTo(Person::players[i]->coords, Person::players[i]->headtarget);
5780         }
5781     }
5782 }
5783
5784
5785
5786 void updateSettingsMenu()
5787 {
5788     char sbuf[256];
5789     if ((float)newscreenwidth > (float)newscreenheight * 1.61 || (float)newscreenwidth < (float)newscreenheight * 1.59)
5790         sprintf (sbuf, "Resolution: %d*%d", (int)newscreenwidth, (int)newscreenheight);
5791     else
5792         sprintf (sbuf, "Resolution: %d*%d (widescreen)", (int)newscreenwidth, (int)newscreenheight);
5793     Menu::setText(0, sbuf);
5794     if (newdetail == 0) Menu::setText(1, "Detail: Low");
5795     if (newdetail == 1) Menu::setText(1, "Detail: Medium");
5796     if (newdetail == 2) Menu::setText(1, "Detail: High");
5797     if (bloodtoggle == 0) Menu::setText(2, "Blood: Off");
5798     if (bloodtoggle == 1) Menu::setText(2, "Blood: On, low detail");
5799     if (bloodtoggle == 2) Menu::setText(2, "Blood: On, high detail (slower)");
5800     if (difficulty == 0) Menu::setText(3, "Difficulty: Easier");
5801     if (difficulty == 1) Menu::setText(3, "Difficulty: Difficult");
5802     if (difficulty == 2) Menu::setText(3, "Difficulty: Insane");
5803     Menu::setText(4, ismotionblur ? "Blur Effects: Enabled (less compatible)" : "Blur Effects: Disabled (more compatible)");
5804     Menu::setText(5, decals ? "Decals: Enabled (slower)" : "Decals: Disabled");
5805     Menu::setText(6, musictoggle ? "Music: Enabled" : "Music: Disabled");
5806     Menu::setText(9, invertmouse ? "Invert mouse: Yes" : "Invert mouse: No");
5807     sprintf (sbuf, "Mouse Speed: %d", (int)(usermousesensitivity * 5));
5808     Menu::setText(10, sbuf);
5809     sprintf (sbuf, "Volume: %d%%", (int)(volume * 100));
5810     Menu::setText(11, sbuf);
5811     Menu::setText(13, showdamagebar ? "Damage Bar: On" : "Damage Bar: Off");
5812     if (newdetail == detail && newscreenheight == (int)screenheight && newscreenwidth == (int)screenwidth)
5813         sprintf (sbuf, "Back");
5814     else
5815         sprintf (sbuf, "Back (some changes take effect next time Lugaru is opened)");
5816     Menu::setText(8, sbuf);
5817 }
5818
5819 void updateStereoConfigMenu()
5820 {
5821     char sbuf[256];
5822     sprintf(sbuf, "Stereo mode: %s", StereoModeName(newstereomode));
5823     Menu::setText(0, sbuf);
5824     sprintf(sbuf, "Stereo separation: %.3f", stereoseparation);
5825     Menu::setText(1, sbuf);
5826     sprintf(sbuf, "Reverse stereo: %s", stereoreverse ? "Yes" : "No");
5827     Menu::setText(2, sbuf);
5828 }
5829
5830 void updateControlsMenu()
5831 {
5832     Menu::setText(0, (string)"Forwards: " + (keyselect == 0 ? "_" : Input::keyToChar(forwardkey)));
5833     Menu::setText(1, (string)"Back: "    + (keyselect == 1 ? "_" : Input::keyToChar(backkey)));
5834     Menu::setText(2, (string)"Left: "    + (keyselect == 2 ? "_" : Input::keyToChar(leftkey)));
5835     Menu::setText(3, (string)"Right: "   + (keyselect == 3 ? "_" : Input::keyToChar(rightkey)));
5836     Menu::setText(4, (string)"Crouch: "  + (keyselect == 4 ? "_" : Input::keyToChar(crouchkey)));
5837     Menu::setText(5, (string)"Jump: "    + (keyselect == 5 ? "_" : Input::keyToChar(jumpkey)));
5838     Menu::setText(6, (string)"Draw: "    + (keyselect == 6 ? "_" : Input::keyToChar(drawkey)));
5839     Menu::setText(7, (string)"Throw: "   + (keyselect == 7 ? "_" : Input::keyToChar(throwkey)));
5840     Menu::setText(8, (string)"Attack: "  + (keyselect == 8 ? "_" : Input::keyToChar(attackkey)));
5841     if (debugmode)
5842         Menu::setText(9, (string)"Console: " + (keyselect == 9 ? "_" : Input::keyToChar(consolekey)));
5843 }
5844
5845 /*
5846 Values of mainmenu :
5847 1 Main menu
5848 2 Menu pause (resume/end game)
5849 3 Option menu
5850 4 Controls configuration menu
5851 5 Main game menu (choose level or challenge)
5852 6 Deleting user menu
5853 7 User managment menu (select/add)
5854 8 Choose difficulty menu
5855 9 Challenge level selection menu
5856 10 End of the campaign congratulation (is that really a menu?)
5857 11 Same that 9 ??? => unused
5858 18 stereo configuration
5859 */
5860
5861 void Game::LoadMenu()
5862 {
5863     Menu::clearMenu();
5864     switch (mainmenu) {
5865     case 1:
5866     case 2:
5867         Menu::addImage(0, Mainmenuitems[0], 150, 480 - 128, 256, 128);
5868         Menu::addButtonImage(1, Mainmenuitems[mainmenu == 1 ? 1 : 5], 18, 480 - 152 - 32, 128, 32);
5869         Menu::addButtonImage(2, Mainmenuitems[2], 18, 480 - 228 - 32, 112, 32);
5870         Menu::addButtonImage(3, Mainmenuitems[mainmenu == 1 ? 3 : 6], 18, 480 - 306 - 32, mainmenu == 1 ? 68 : 132, 32);
5871         break;
5872     case 3:
5873         Menu::addButton( 0, "", 10 + 20, 440);
5874         Menu::addButton( 1, "", 10 + 60, 405);
5875         Menu::addButton( 2, "", 10 + 70, 370);
5876         Menu::addButton( 3, "", 10 + 20 - 1000, 335 - 1000);
5877         Menu::addButton( 4, "", 10   , 335);
5878         Menu::addButton( 5, "", 10 + 60, 300);
5879         Menu::addButton( 6, "", 10 + 70, 265);
5880         Menu::addButton( 9, "", 10   , 230);
5881         Menu::addButton(10, "", 20   , 195);
5882         Menu::addButton(11, "", 10 + 60, 160);
5883         Menu::addButton(13, "", 30   , 125);
5884         Menu::addButton( 7, "-Configure Controls-", 10 + 15, 90);
5885         Menu::addButton(12, "-Configure Stereo -", 10 + 15, 55);
5886         Menu::addButton(8, "Back", 10, 10);
5887         updateSettingsMenu();
5888         break;
5889     case 4:
5890         Menu::addButton(0, "", 10   , 400);
5891         Menu::addButton(1, "", 10 + 40, 360);
5892         Menu::addButton(2, "", 10 + 40, 320);
5893         Menu::addButton(3, "", 10 + 30, 280);
5894         Menu::addButton(4, "", 10 + 20, 240);
5895         Menu::addButton(5, "", 10 + 40, 200);
5896         Menu::addButton(6, "", 10 + 40, 160);
5897         Menu::addButton(7, "", 10 + 30, 120);
5898         Menu::addButton(8, "", 10 + 20, 80);
5899         if (debugmode)
5900             Menu::addButton(9, "", 10 + 10, 40);
5901         Menu::addButton(debugmode ? 10 : 9, "Back", 10, 10);
5902         updateControlsMenu();
5903         break;
5904     case 5: {
5905         LoadCampaign();
5906         Menu::addLabel(-1, accountactive->getName(), 5, 400);
5907         Menu::addButton(1, "Tutorial", 5, 300);
5908         Menu::addButton(2, "Challenge", 5, 240);
5909         Menu::addButton(3, "Delete User", 400, 10);
5910         Menu::addButton(4, "Main Menu", 5, 10);
5911         Menu::addButton(5, "Change User", 5, 180);
5912         Menu::addButton(6, "Campaign : " + accountactive->getCurrentCampaign(), 200, 420);
5913
5914         //show campaign map
5915         //with (2,-5) offset from old code
5916         Menu::addImage(-1, Mainmenuitems[7], 150 + 2, 60 - 5, 400, 400);
5917         //show levels
5918         int numlevels = accountactive->getCampaignChoicesMade();
5919         numlevels += numlevels > 0 ? campaignlevels[numlevels - 1].nextlevel.size() : 1;
5920         for (int i = 0; i < numlevels; i++) {
5921             XYZ midpoint = campaignlevels[i].getCenter();
5922             float itemsize = campaignlevels[i].getWidth();
5923             const bool active = i >= accountactive->getCampaignChoicesMade();
5924             if (!active)
5925                 itemsize /= 2;
5926
5927             if (i >= 1) {
5928                 XYZ start = campaignlevels[i - 1].getCenter();
5929                 Menu::addMapLine(start.x, start.y, midpoint.x - start.x, midpoint.y - start.y, 0.5, active ? 1 : 0.5, active ? 1 : 0.5, 0, 0);
5930             }
5931             Menu::addMapMarker(NB_CAMPAIGN_MENU_ITEM + i, Mapcircletexture,
5932                                midpoint.x - itemsize / 2, midpoint.y - itemsize / 2, itemsize, itemsize, active ? 1 : 0.5, 0, 0);
5933
5934             if (active) {
5935                 Menu::addMapLabel(-2, campaignlevels[i].description,
5936                                   campaignlevels[i].getStartX() + 10,
5937                                   campaignlevels[i].getStartY() - 4);
5938             }
5939         }
5940     }
5941     break;
5942     case 6:
5943         Menu::addLabel(-1, "Are you sure you want to delete this user?", 10, 400);
5944         Menu::addButton(1, "Yes", 10, 360);
5945         Menu::addButton(2, "No", 10, 320);
5946         break;
5947     case 7:
5948         if (Account::getNbAccounts() < 8)
5949             Menu::addButton(0, "New User", 10, 400);
5950         else
5951             Menu::addLabel(0, "No More Users", 10, 400);
5952         Menu::addLabel(-2, "", 20, 400);
5953         Menu::addButton(Account::getNbAccounts() + 1, "Back", 10, 10);
5954         for (int i = 0; i < Account::getNbAccounts(); i++)
5955             Menu::addButton(i + 1, Account::get(i)->getName(), 10, 340 - 20 * (i + 1));
5956         break;
5957     case 8:
5958         Menu::addButton(0, "Easier", 10, 400);
5959         Menu::addButton(1, "Difficult", 10, 360);
5960         Menu::addButton(2, "Insane", 10, 320);
5961         break;
5962     case 9:
5963         for (int i = 0; i < numchallengelevels; i++) {
5964             char temp[255];
5965             string name = "";
5966             sprintf (temp, "Level %d", i + 1);
5967             for (int j = strlen(temp); j < 17; j++)
5968                 strcat(temp, " ");
5969             name += temp;
5970             sprintf (temp, "%d", (int)accountactive->getHighScore(i));
5971             for (int j = strlen(temp); j < (32 - 17); j++)
5972                 strcat(temp, " ");
5973             name += temp;
5974             sprintf (temp, "%d:", (int)(((int)accountactive->getFastTime(i) - (int)(accountactive->getFastTime(i)) % 60) / 60));
5975             if ((int)(accountactive->getFastTime(i)) % 60 < 10)
5976                 strcat(temp, "0");
5977             name += temp;
5978             sprintf (temp, "%d", (int)(accountactive->getFastTime(i)) % 60);
5979             name += temp;
5980
5981             Menu::addButton(i, name, 10, 400 - i * 25, i > accountactive->getProgress() ? 0.5 : 1, 0, 0);
5982         }
5983
5984         Menu::addButton(-1, "             High Score      Best Time", 10, 440);
5985         Menu::addButton(numchallengelevels, "Back", 10, 10);
5986         break;
5987     case 10: {
5988         Menu::addLabel(0, "Congratulations!", 220, 330);
5989         Menu::addLabel(1, "You have avenged your family and", 140, 300);
5990         Menu::addLabel(2, "restored peace to the island of Lugaru.", 110, 270);
5991         Menu::addButton(3, "Back", 10, 10);
5992         char sbuf[256];
5993         sprintf(sbuf, "Your score:         %d", (int)accountactive->getCampaignScore());
5994         Menu::addLabel(4, sbuf, 190, 200);
5995         sprintf(sbuf, "Highest score:      %d", (int)accountactive->getCampaignHighScore());
5996         Menu::addLabel(5, sbuf, 190, 180);
5997     }
5998     break;
5999     case 18:
6000         Menu::addButton(0, "", 70, 400);
6001         Menu::addButton(1, "", 10, 360);
6002         Menu::addButton(2, "", 40, 320);
6003         Menu::addButton(3, "Back", 10, 10);
6004         updateStereoConfigMenu();
6005         break;
6006     }
6007 }
6008
6009 extern SDL_Rect **resolutions;
6010
6011 void MenuTick()
6012 {
6013     //menu buttons
6014     selected = Menu::getSelected(mousecoordh * 640 / screenwidth, 480 - mousecoordv * 480 / screenheight);
6015
6016     // some specific case where we do something even if the left mouse button is not pressed.
6017     if ((mainmenu == 5) && (endgame == 2)) {
6018         accountactive->endGame();
6019         endgame = 0;
6020     }
6021     if (mainmenu == 10)
6022         endgame = 2;
6023     if (mainmenu == 18 && Input::isKeyPressed(MOUSEBUTTON2) && selected == 1) {
6024         stereoseparation -= 0.001;
6025         updateStereoConfigMenu();
6026     }
6027
6028     static int oldmainmenu = mainmenu;
6029
6030     char sbuf[256];
6031
6032     if (Input::MouseClicked() && (selected >= 0)) { // handling of the left mouse clic in menus
6033         switch (mainmenu) {
6034         case 1:
6035         case 2:
6036             switch (selected) {
6037             case 1:
6038                 if (gameon) { //resume
6039                     mainmenu = 0;
6040                     pause_sound(stream_menutheme);
6041                     resume_stream(leveltheme);
6042                 } else { //new game
6043                     fireSound(firestartsound);
6044                     flash();
6045                     mainmenu = (accountactive ? 5 : 7);
6046                     selected = -1;
6047                 }
6048                 break;
6049             case 2: //options
6050                 fireSound();
6051                 flash();
6052                 mainmenu = 3;
6053                 if (newdetail > 2)
6054                     newdetail = detail;
6055                 if (newdetail < 0)
6056                     newdetail = detail;
6057                 if (newscreenwidth > 3000)
6058                     newscreenwidth = screenwidth;
6059                 if (newscreenwidth < 0)
6060                     newscreenwidth = screenwidth;
6061                 if (newscreenheight > 3000)
6062                     newscreenheight = screenheight;
6063                 if (newscreenheight < 0)
6064                     newscreenheight = screenheight;
6065                 break;
6066             case 3:
6067                 fireSound();
6068                 flash();
6069                 if (gameon) { //end game
6070                     gameon = 0;
6071                     mainmenu = 1;
6072                 } else { //quit
6073                     tryquit = 1;
6074                     pause_sound(stream_menutheme);
6075                 }
6076                 break;
6077             }
6078             break;
6079         case 3:
6080             fireSound();
6081             bool isCustomResolution, found;
6082             switch (selected) {
6083             case 0:
6084                 isCustomResolution = true;
6085                 found = false;
6086                 for (int i = 0; (!found) && (resolutions[i]); i++) {
6087                     if ((resolutions[i]->w == screenwidth) && (resolutions[i]->h == screenwidth))
6088                         isCustomResolution = false;
6089
6090                     if ((resolutions[i]->w == newscreenwidth) && (resolutions[i]->h == newscreenheight)) {
6091                         i++;
6092                         if (resolutions[i] != NULL) {
6093                             newscreenwidth = (int) resolutions[i]->w;
6094                             newscreenheight = (int) resolutions[i]->h;
6095                         } else if (isCustomResolution) {
6096                             if ((screenwidth == newscreenwidth) && (screenheight == newscreenheight)) {
6097                                 newscreenwidth = (int) resolutions[0]->w;
6098                                 newscreenheight = (int) resolutions[0]->h;
6099                             } else {
6100                                 newscreenwidth = screenwidth;
6101                                 newscreenheight = screenheight;
6102                             }
6103                         } else {
6104                             newscreenwidth = (int) resolutions[0]->w;
6105                             newscreenheight = (int) resolutions[0]->h;
6106                         }
6107                         found = true;
6108                     }
6109                 }
6110
6111                 if (!found) {
6112                     newscreenwidth = (int) resolutions[0]->w;
6113                     newscreenheight = (int) resolutions[0]->h;
6114                 }
6115                 break;
6116             case 1:
6117                 newdetail++;
6118                 if (newdetail > 2)
6119                     newdetail = 0;
6120                 break;
6121             case 2:
6122                 bloodtoggle++;
6123                 if (bloodtoggle > 2)
6124                     bloodtoggle = 0;
6125                 break;
6126             case 3:
6127                 difficulty++;
6128                 if (difficulty > 2)
6129                     difficulty = 0;
6130                 break;
6131             case 4:
6132                 ismotionblur = !ismotionblur;
6133                 break;
6134             case 5:
6135                 decals = !decals;
6136                 break;
6137             case 6:
6138                 musictoggle = !musictoggle;
6139                 if (musictoggle) {
6140                     emit_stream_np(stream_menutheme);
6141                 } else {
6142                     pause_sound(leveltheme);
6143                     pause_sound(stream_fighttheme);
6144                     pause_sound(stream_menutheme);
6145
6146                     for (int i = 0; i < 4; i++) {
6147                         oldmusicvolume[i] = 0;
6148                         musicvolume[i] = 0;
6149                     }
6150                 }
6151                 break;
6152             case 7: // controls
6153                 flash();
6154                 mainmenu = 4;
6155                 selected = -1;
6156                 keyselect = -1;
6157                 break;
6158             case 8:
6159                 flash();
6160                 SaveSettings();
6161                 mainmenu = gameon ? 2 : 1;
6162                 break;
6163             case 9:
6164                 invertmouse = !invertmouse;
6165                 break;
6166             case 10:
6167                 usermousesensitivity += .2;
6168                 if (usermousesensitivity > 2)
6169                     usermousesensitivity = .2;
6170                 break;
6171             case 11:
6172                 volume += .1f;
6173                 if (volume > 1.0001f)
6174                     volume = 0;
6175                 OPENAL_SetSFXMasterVolume((int)(volume * 255));
6176                 break;
6177             case 12:
6178                 flash();
6179                 newstereomode = stereomode;
6180                 mainmenu = 18;
6181                 keyselect = -1;
6182                 break;
6183             case 13:
6184                 showdamagebar = !showdamagebar;
6185                 break;
6186             }
6187             updateSettingsMenu();
6188             break;
6189         case 4:
6190             if (!waiting) {
6191                 fireSound();
6192                 if (selected < (debugmode ? 10 : 9) && keyselect == -1)
6193                     keyselect = selected;
6194                 if (keyselect != -1)
6195                     setKeySelected();
6196                 if (selected == (debugmode ? 10 : 9)) {
6197                     flash();
6198                     mainmenu = 3;
6199                 }
6200             }
6201             updateControlsMenu();
6202             break;
6203         case 5:
6204             fireSound();
6205             flash();
6206             if ((selected - NB_CAMPAIGN_MENU_ITEM >= accountactive->getCampaignChoicesMade())) {
6207                 startbonustotal = 0;
6208
6209                 loading = 2;
6210                 loadtime = 0;
6211                 targetlevel = 7;
6212                 if (firstload)
6213                     TickOnceAfter();
6214                 else
6215                     LoadStuff();
6216                 whichchoice = selected - NB_CAMPAIGN_MENU_ITEM - accountactive->getCampaignChoicesMade();
6217                 actuallevel = (accountactive->getCampaignChoicesMade() > 0 ? campaignlevels[accountactive->getCampaignChoicesMade() - 1].nextlevel[whichchoice] : 0);
6218                 visibleloading = 1;
6219                 stillloading = 1;
6220                 Loadlevel(campaignlevels[actuallevel].mapname.c_str());
6221                 campaign = 1;
6222                 mainmenu = 0;
6223                 gameon = 1;
6224                 pause_sound(stream_menutheme);
6225             }
6226             switch (selected) {
6227             case 1:
6228                 startbonustotal = 0;
6229
6230                 loading = 2;
6231                 loadtime = 0;
6232                 targetlevel = -1;
6233                 if (firstload) {
6234                     TickOnceAfter();
6235                 } else
6236                     LoadStuff();
6237                 Loadlevel(-1);
6238
6239                 mainmenu = 0;
6240                 gameon = 1;
6241                 pause_sound(stream_menutheme);
6242                 break;
6243             case 2:
6244                 mainmenu = 9;
6245                 break;
6246             case 3:
6247                 mainmenu = 6;
6248                 break;
6249             case 4:
6250                 mainmenu = (gameon ? 2 : 1);
6251                 break;
6252             case 5:
6253                 mainmenu = 7;
6254                 break;
6255             case 6:
6256                 vector<string> campaigns = ListCampaigns();
6257                 vector<string>::iterator c;
6258                 if ((c = find(campaigns.begin(), campaigns.end(), accountactive->getCurrentCampaign())) == campaigns.end()) {
6259                     if (!campaigns.empty())
6260                         accountactive->setCurrentCampaign(campaigns.front());
6261                 } else {
6262                     c++;
6263                     if (c == campaigns.end())
6264                         c = campaigns.begin();
6265                     accountactive->setCurrentCampaign(*c);
6266                 }
6267                 LoadMenu();
6268                 break;
6269             }
6270             break;
6271         case 6:
6272             fireSound();
6273             if (selected == 1) {
6274                 flash();
6275                 accountactive = Account::destroy(accountactive);
6276                 mainmenu = 7;
6277             } else if (selected == 2) {
6278                 flash();
6279                 mainmenu = 5;
6280             }
6281             break;
6282         case 7:
6283             fireSound();
6284             if (selected == 0 && Account::getNbAccounts() < 8) {
6285                 entername = 1;
6286             } else if (selected < Account::getNbAccounts() + 1) {
6287                 flash();
6288                 mainmenu = 5;
6289                 accountactive = Account::get(selected - 1);
6290             } else if (selected == Account::getNbAccounts() + 1) {
6291                 flash();
6292                 if (accountactive)
6293                     mainmenu = 5;
6294                 else
6295                     mainmenu = 1;
6296                 for (int j = 0; j < 255; j++) {
6297                     displaytext[0][j] = 0;
6298                 }
6299                 displaychars[0] = 0;
6300                 displayselected = 0;
6301                 entername = 0;
6302             }
6303             break;
6304         case 8:
6305             fireSound();
6306             flash();
6307             if (selected <= 2)
6308                 accountactive->setDifficulty(selected);
6309             mainmenu = 5;
6310             break;
6311         case 9:
6312             if (selected < numchallengelevels && selected <= accountactive->getProgress()) {
6313                 fireSound();
6314                 flash();
6315
6316                 startbonustotal = 0;
6317
6318                 loading = 2;
6319                 loadtime = 0;
6320                 targetlevel = selected;
6321                 if (firstload)
6322                     TickOnceAfter();
6323                 else
6324                     LoadStuff();
6325                 Loadlevel(selected);
6326                 campaign = 0;
6327
6328                 mainmenu = 0;
6329                 gameon = 1;
6330                 pause_sound(stream_menutheme);
6331             }
6332             if (selected == numchallengelevels) {
6333                 fireSound();
6334                 flash();
6335                 mainmenu = 5;
6336             }
6337             break;
6338         case 10:
6339             if (selected == 3) {
6340                 fireSound();
6341                 flash();
6342                 mainmenu = 5;
6343             }
6344             break;
6345         case 18:
6346             if (selected == 1)
6347                 stereoseparation += 0.001;
6348             else {
6349                 fireSound();
6350                 if (selected == 0) {
6351                     newstereomode = (StereoMode)(newstereomode + 1);
6352                     while (!CanInitStereo(newstereomode)) {
6353                         printf("Failed to initialize mode %s (%i)\n", StereoModeName(newstereomode), newstereomode);
6354                         newstereomode = (StereoMode)(newstereomode + 1);
6355                         if (newstereomode >= stereoCount)
6356                             newstereomode = stereoNone;
6357                     }
6358                 } else if (selected == 2) {
6359                     stereoreverse = !stereoreverse;
6360                 } else if (selected == 3) {
6361                     flash();
6362                     mainmenu = 3;
6363
6364                     stereomode = newstereomode;
6365                     InitStereo(stereomode);
6366                 }
6367             }
6368             updateStereoConfigMenu();
6369             break;
6370         }
6371     }
6372
6373     if (Input::isKeyDown(SDLK_q) && Input::isKeyDown(SDLK_LMETA)) {
6374         tryquit = 1;
6375         if (mainmenu == 3) {
6376             SaveSettings();
6377         }
6378     }
6379
6380     OPENAL_SetFrequency(channels[stream_menutheme], 22050);
6381
6382     if (entername) {
6383         inputText(displaytext[0], &displayselected, &displaychars[0]);
6384         if (!waiting) { // the input as finished
6385             if (displaychars[0]) { // with enter
6386                 accountactive = Account::add(string(displaytext[0]));
6387
6388                 mainmenu = 8;
6389
6390                 flash();
6391
6392                 fireSound(firestartsound);
6393
6394                 for (int i = 0; i < 255; i++) {
6395                     displaytext[0][i] = 0;
6396                 }
6397                 displaychars[0] = 0;
6398
6399                 displayselected = 0;
6400             }
6401             entername = 0;
6402             LoadMenu();
6403         }
6404
6405         displayblinkdelay -= multiplier;
6406         if (displayblinkdelay <= 0) {
6407             displayblinkdelay = .3;
6408             displayblink = 1 - displayblink;
6409         }
6410     }
6411
6412     if (entername) {
6413         Menu::setText(0, displaytext[0], 20, 400, -1, -1);
6414         Menu::setText(-2, displayblink ? "_" : "", 20 + displayselected * 10, 400, -1, -1);
6415     }
6416
6417     if (oldmainmenu != mainmenu)
6418         LoadMenu();
6419     oldmainmenu = mainmenu;
6420
6421 }
6422
6423 void Game::Tick()
6424 {
6425     static XYZ facing, flatfacing;
6426     static int target;
6427
6428     for (int i = 0; i < 15; i++) {
6429         displaytime[i] += multiplier;
6430     }
6431
6432     keyboardfrozen = false;
6433     Input::Tick();
6434
6435     if (Input::isKeyPressed(SDLK_F6)) {
6436         if (Input::isKeyDown(SDLK_LSHIFT))
6437             stereoreverse = true;
6438         else
6439             stereoreverse = false;
6440
6441         if (stereoreverse)
6442             printf("Stereo reversed\n");
6443         else
6444             printf("Stereo unreversed\n");
6445     }
6446
6447     if (Input::isKeyDown(SDLK_F7)) {
6448         if (Input::isKeyDown(SDLK_LSHIFT))
6449             stereoseparation -= 0.001;
6450         else
6451             stereoseparation -= 0.010;
6452         printf("Stereo decreased increased to %f\n", stereoseparation);
6453     }
6454
6455     if (Input::isKeyDown(SDLK_F8)) {
6456         if (Input::isKeyDown(SDLK_LSHIFT))
6457             stereoseparation += 0.001;
6458         else
6459             stereoseparation += 0.010;
6460         printf("Stereo separation increased to %f\n", stereoseparation);
6461     }
6462
6463
6464     if (Input::isKeyPressed(SDLK_TAB) && tutoriallevel) {
6465         if (tutorialstage != 51)
6466             tutorialstagetime = tutorialmaxtime;
6467         emit_sound_np(consolefailsound, 128.);
6468     }
6469
6470     /*
6471     Values of mainmenu :
6472     1 Main menu
6473     2 Menu pause (resume/end game)
6474     3 Option menu
6475     4 Controls configuration menu
6476     5 Main game menu (choose level or challenge)
6477     6 Deleting user menu
6478     7 User managment menu (select/add)
6479     8 Choose difficulty menu
6480     9 Challenge level selection menu
6481     10 End of the campaign congratulation (is that really a menu?)
6482     11 Same that 9 ??? => unused
6483     18 stereo configuration
6484     */
6485
6486     if (!console) {
6487         //campaign over?
6488         if (mainmenu && endgame == 1)
6489             mainmenu = 10;
6490         //go to level select after completing a campaign level
6491         if (campaign && winfreeze && mainmenu == 0 && campaignlevels[actuallevel].choosenext == 1) {
6492             mainmenu = 5;
6493             gameon = 0;
6494             winfreeze = 0;
6495             fireSound();
6496             flash();
6497             if (musictoggle) {
6498                 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6499                 emit_stream_np(stream_menutheme);
6500                 pause_sound(leveltheme);
6501             }
6502             LoadMenu();
6503         }
6504         //escape key pressed
6505         if (Input::isKeyPressed(SDLK_ESCAPE) &&
6506                 (gameon || mainmenu == 0 || (mainmenu >= 3 && mainmenu != 8 && !(mainmenu == 7 && entername)))) {
6507             selected = -1;
6508             if (mainmenu == 0 && !winfreeze)
6509                 mainmenu = 2; //pause
6510             else if (mainmenu == 1 || mainmenu == 2) {
6511                 mainmenu = 0; //unpause
6512             }
6513             //play menu theme
6514             if (musictoggle && (mainmenu == 1 || mainmenu == 2)) {
6515                 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6516                 emit_stream_np(stream_menutheme);
6517                 pause_sound(leveltheme);
6518             }
6519             //on resume, play level music
6520             if (!mainmenu) {
6521                 pause_sound(stream_menutheme);
6522                 resume_stream(leveltheme);
6523             }
6524             //finished with settings menu
6525             if (mainmenu == 3) {
6526                 SaveSettings();
6527             }
6528             //effects
6529             if (mainmenu >= 3 && mainmenu != 8) {
6530                 fireSound();
6531                 flash();
6532             }
6533             //go back
6534             switch (mainmenu) {
6535             case 3:
6536             case 5:
6537                 mainmenu = gameon ? 2 : 1;
6538                 break;
6539             case 4:
6540             case 18:
6541                 mainmenu = 3;
6542                 break;
6543             case 6:
6544             case 7:
6545             case 9:
6546             case 10:
6547                 mainmenu = 5;
6548                 break;
6549             }
6550         }
6551     }
6552
6553     if (mainmenu) {
6554         MenuTick();
6555     }
6556
6557     if (!mainmenu) {
6558         if (hostile == 1)
6559             hostiletime += multiplier;
6560         else
6561             hostiletime = 0;
6562         if (!winfreeze)
6563             leveltime += multiplier;
6564
6565         //keys
6566         if (Input::isKeyPressed(SDLK_v) && debugmode) {
6567             freeze = 1 - freeze;
6568             if (freeze) {
6569                 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6570             }
6571         }
6572
6573         if (Input::isKeyPressed(chatkey) && !console && !chatting && debugmode)
6574             chatting = 1;
6575
6576         if (chatting) {
6577             inputText(displaytext[0], &displayselected, &displaychars[0]);
6578             if (!waiting) {
6579                 if (displaychars[0]) {
6580                     for (int j = 0; j < 255; j++)
6581                         displaytext[0][j] = 0;
6582                     displaychars[0] = 0;
6583                     displayselected = 0;
6584                 }
6585                 chatting = 0;
6586             }
6587
6588             displayblinkdelay -= multiplier;
6589             if (displayblinkdelay <= 0) {
6590                 displayblinkdelay = .3;
6591                 displayblink = 1 - displayblink;
6592             }
6593         }
6594         if (chatting)
6595             keyboardfrozen = true;
6596
6597         if (Input::isKeyPressed(consolekey) && debugmode) {
6598             console = !console;
6599             if (console) {
6600                 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6601             } else {
6602                 freeze = 0;
6603                 waiting = false;
6604             }
6605         }
6606
6607         if (console)
6608             freeze = 1;
6609         if (console && !Input::isKeyDown(SDLK_LMETA)) {
6610             inputText(consoletext[0], &consoleselected, &consolechars[0]);
6611             if (!waiting) {
6612                 if (consolechars[0] > 0) {
6613                     consoletext[0][consolechars[0]] = '\0';
6614                     cmd_dispatch(consoletext[0]);
6615                     for (int k = 14; k >= 1; k--) {
6616                         for (int j = 0; j < 255; j++)
6617                             consoletext[k][j] = consoletext[k - 1][j];
6618                         consolechars[k] = consolechars[k - 1];
6619                     }
6620                     for (int j = 0; j < 255; j++)
6621                         consoletext[0][j] = 0;
6622                     consolechars[0] = 0;
6623                     consoleselected = 0;
6624                 }
6625             }
6626
6627             consoleblinkdelay -= multiplier;
6628             if (consoleblinkdelay <= 0) {
6629                 consoleblinkdelay = .3;
6630                 consoleblink = 1 - consoleblink;
6631             }
6632         }
6633
6634
6635
6636         if (Input::isKeyDown(SDLK_q) && Input::isKeyDown(SDLK_LMETA)) {
6637             tryquit = 1;
6638             if (mainmenu == 3) {
6639                 SaveSettings();
6640             }
6641         }
6642
6643         static int oldwinfreeze;
6644         if (winfreeze && !oldwinfreeze) {
6645             OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6646             emit_sound_np(consolesuccesssound);
6647         }
6648         if (winfreeze == 0)
6649             oldwinfreeze = winfreeze;
6650         else
6651             oldwinfreeze++;
6652
6653         if ((Input::isKeyPressed(jumpkey) || Input::isKeyPressed(SDLK_SPACE)) && !campaign)
6654             if (winfreeze)
6655                 winfreeze = 0;
6656         if ((Input::isKeyDown(SDLK_ESCAPE)) && !campaign && gameon) {
6657             if (console) {
6658                 console = false;
6659                 freeze = 0;
6660             } else if (winfreeze) {
6661                 mainmenu = 9;
6662                 gameon = 0;
6663             }
6664         }
6665
6666
6667
6668         if (!freeze && !winfreeze && !(mainmenu && gameon) && (gameon || !gamestarted)) {
6669
6670             //dialogues
6671             static float talkdelay = 0;
6672
6673             if (indialogue != -1)
6674                 talkdelay = 1;
6675             talkdelay -= multiplier;
6676
6677             if (talkdelay <= 0 && indialogue == -1 && animation[Person::players[0]->animTarget].height != highheight)
6678                 for (int i = 0; i < numdialogues; i++) {
6679                     int realdialoguetype;
6680                     bool special;
6681                     if (dialoguetype[i] > 49) {
6682                         realdialoguetype = dialoguetype[i] - 50;
6683                         special = 1;
6684                     } else if (dialoguetype[i] > 39) {
6685                         realdialoguetype = dialoguetype[i] - 40;
6686                         special = 1;
6687                     } else if (dialoguetype[i] > 29) {
6688                         realdialoguetype = dialoguetype[i] - 30;
6689                         special = 1;
6690                     } else if (dialoguetype[i] > 19) {
6691                         realdialoguetype = dialoguetype[i] - 20;
6692                         special = 1;
6693                     } else if (dialoguetype[i] > 9) {
6694                         realdialoguetype = dialoguetype[i] - 10;
6695                         special = 1;
6696                     } else {
6697                         realdialoguetype = dialoguetype[i];
6698                         special = 0;
6699                     }
6700                     if ((!hostile || dialoguetype[i] > 40 && dialoguetype[i] < 50) &&
6701                             realdialoguetype < numplayers &&
6702                             realdialoguetype > 0 &&
6703                             (dialoguegonethrough[i] == 0 || !special) &&
6704                             (special || Input::isKeyPressed(attackkey))) {
6705                         if (distsq(&Person::players[0]->coords, &Person::players[realdialoguetype]->coords) < 6 ||
6706                                 Person::players[realdialoguetype]->howactive >= typedead1 ||
6707                                 dialoguetype[i] > 40 && dialoguetype[i] < 50) {
6708                             whichdialogue = i;
6709                             for (int j = 0; j < numdialogueboxes[whichdialogue]; j++) {
6710                                 Person::players[participantfocus[whichdialogue][j]]->coords = participantlocation[whichdialogue][participantfocus[whichdialogue][j]];
6711                                 Person::players[participantfocus[whichdialogue][j]]->yaw = participantyaw[whichdialogue][participantfocus[whichdialogue][j]];
6712                                 Person::players[participantfocus[whichdialogue][j]]->targetyaw = participantyaw[whichdialogue][participantfocus[whichdialogue][j]];
6713                                 Person::players[participantfocus[whichdialogue][j]]->velocity = 0;
6714                                 Person::players[participantfocus[whichdialogue][j]]->animTarget = Person::players[participantfocus[whichdialogue][j]]->getIdle();
6715                                 Person::players[participantfocus[whichdialogue][j]]->frameTarget = 0;
6716                             }
6717                             directing = 0;
6718                             indialogue = 0;
6719                             dialoguetime = 0;
6720                             dialoguegonethrough[i]++;
6721                             if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6722                                 playdialogueboxsound();
6723                             }
6724                         }
6725                     }
6726                 }
6727
6728             windvar += multiplier;
6729             smoketex += multiplier;
6730             tutorialstagetime += multiplier;
6731
6732             //hotspots
6733             static float hotspotvisual[40];
6734             if (numhotspots) {
6735                 XYZ hotspotsprite;
6736                 if (editorenabled)
6737                     for (int i = 0; i < numhotspots; i++)
6738                         hotspotvisual[i] -= multiplier / 320;
6739
6740                 for (int i = 0; i < numhotspots; i++) {
6741                     //if(hotspottype[i]<=10)
6742                     while (hotspotvisual[i] < 0) {
6743                         hotspotsprite = 0;
6744                         hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * hotspotsize[i];
6745                         hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
6746                         hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
6747                         hotspotsprite += hotspot[i];
6748                         Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
6749                         hotspotvisual[i] += 0.1 / hotspotsize[i] / hotspotsize[i] / hotspotsize[i];
6750                     }
6751                 }
6752
6753                 for (int i = 0; i < numhotspots; i++) {
6754                     if (hotspottype[i] <= 10 && hotspottype[i] > 0) {
6755                         hotspot[i] = Person::players[hotspottype[i]]->coords;
6756                     }
6757                 }
6758             }
6759
6760             //Tutorial
6761             if (tutoriallevel) {
6762                 doTutorial();
6763             }
6764
6765             //bonuses
6766             if (tutoriallevel != 1) {
6767                 if (bonustime == 0 &&
6768                         bonus != solidhit &&
6769                         bonus != spinecrusher &&
6770                         bonus != tracheotomy &&
6771                         bonus != backstab &&
6772                         bonusvalue > 10) {
6773                     emit_sound_np(consolesuccesssound);
6774                 }
6775             } else if (bonustime == 0) {
6776                 emit_sound_np(fireendsound);
6777             }
6778             if (bonustime == 0) {
6779                 if (bonus != solidhit &&
6780                         bonus != twoxcombo &&
6781                         bonus != threexcombo &&
6782                         bonus != fourxcombo &&
6783                         bonus != megacombo)
6784                     bonusnum[bonus]++;
6785                 else
6786                     bonusnum[bonus] += 0.15;
6787                 if (tutoriallevel)
6788                     bonusvalue = 0;
6789                 bonusvalue /= bonusnum[bonus];
6790                 bonustotal += bonusvalue;
6791             }
6792             bonustime += multiplier;
6793
6794             //snow effects
6795             if (environment == snowyenvironment) {
6796                 precipdelay -= multiplier;
6797                 while (precipdelay < 0) {
6798                     precipdelay += .04;
6799                     if (!detail)
6800                         precipdelay += .04;
6801                     XYZ footvel, footpoint;
6802
6803                     footvel = 0;
6804                     footpoint = viewer + viewerfacing * 6;
6805                     footpoint.y += ((float)abs(Random() % 1200)) / 100 - 6;
6806                     footpoint.x += ((float)abs(Random() % 1200)) / 100 - 6;
6807                     footpoint.z += ((float)abs(Random() % 1200)) / 100 - 6;
6808                     Sprite::MakeSprite(snowsprite, footpoint, footvel, 1, 1, 1, .1, 1);
6809                 }
6810             }
6811
6812
6813             doAerialAcrobatics();
6814
6815
6816             static XYZ oldviewer;
6817
6818             //control keys
6819             if (indialogue == -1) {
6820                 Person::players[0]->forwardkeydown = Input::isKeyDown(forwardkey);
6821                 Person::players[0]->leftkeydown = Input::isKeyDown(leftkey);
6822                 Person::players[0]->backkeydown = Input::isKeyDown(backkey);
6823                 Person::players[0]->rightkeydown = Input::isKeyDown(rightkey);
6824                 Person::players[0]->jumpkeydown = Input::isKeyDown(jumpkey);
6825                 Person::players[0]->crouchkeydown = Input::isKeyDown(crouchkey);
6826                 Person::players[0]->drawkeydown = Input::isKeyDown(drawkey);
6827                 Person::players[0]->throwkeydown = Input::isKeyDown(throwkey);
6828             } else {
6829                 Person::players[0]->forwardkeydown = 0;
6830                 Person::players[0]->leftkeydown = 0;
6831                 Person::players[0]->backkeydown = 0;
6832                 Person::players[0]->rightkeydown = 0;
6833                 Person::players[0]->jumpkeydown = 0;
6834                 Person::players[0]->crouchkeydown = 0;
6835                 Person::players[0]->drawkeydown = 0;
6836                 Person::players[0]->throwkeydown = 0;
6837             }
6838
6839             if (!Person::players[0]->jumpkeydown)
6840                 Person::players[0]->jumpclimb = 0;
6841
6842
6843             if (indialogue != -1) {
6844                 cameramode = 1;
6845                 if (directing) {
6846                     facing = 0;
6847                     facing.z = -1;
6848
6849                     facing = DoRotation(facing, -pitch, 0, 0);
6850                     facing = DoRotation(facing, 0, 0 - yaw, 0);
6851
6852                     flatfacing = 0;
6853                     flatfacing.z = -1;
6854
6855                     flatfacing = DoRotation(flatfacing, 0, -yaw, 0);
6856
6857                     if (Input::isKeyDown(forwardkey))
6858                         viewer += facing * multiplier * 4;
6859                     if (Input::isKeyDown(backkey))
6860                         viewer -= facing * multiplier * 4;
6861                     if (Input::isKeyDown(leftkey))
6862                         viewer += DoRotation(flatfacing * multiplier, 0, 90, 0) * 4;
6863                     if (Input::isKeyDown(rightkey))
6864                         viewer += DoRotation(flatfacing * multiplier, 0, -90, 0) * 4;
6865                     if (Input::isKeyDown(jumpkey))
6866                         viewer.y += multiplier * 4;
6867                     if (Input::isKeyDown(crouchkey))
6868                         viewer.y -= multiplier * 4;
6869                     if (     Input::isKeyPressed(SDLK_1) ||
6870                              Input::isKeyPressed(SDLK_2) ||
6871                              Input::isKeyPressed(SDLK_3) ||
6872                              Input::isKeyPressed(SDLK_4) ||
6873                              Input::isKeyPressed(SDLK_5) ||
6874                              Input::isKeyPressed(SDLK_6) ||
6875                              Input::isKeyPressed(SDLK_7) ||
6876                              Input::isKeyPressed(SDLK_8) ||
6877                              Input::isKeyPressed(SDLK_9) ||
6878                              Input::isKeyPressed(SDLK_0) ||
6879                              Input::isKeyPressed(SDLK_MINUS)) {
6880                         int whichend;
6881                         if (Input::isKeyPressed(SDLK_1)) whichend = 1;
6882                         if (Input::isKeyPressed(SDLK_2)) whichend = 2;
6883                         if (Input::isKeyPressed(SDLK_3)) whichend = 3;
6884                         if (Input::isKeyPressed(SDLK_4)) whichend = 4;
6885                         if (Input::isKeyPressed(SDLK_5)) whichend = 5;
6886                         if (Input::isKeyPressed(SDLK_6)) whichend = 6;
6887                         if (Input::isKeyPressed(SDLK_7)) whichend = 7;
6888                         if (Input::isKeyPressed(SDLK_8)) whichend = 8;
6889                         if (Input::isKeyPressed(SDLK_9)) whichend = 9;
6890                         if (Input::isKeyPressed(SDLK_0)) whichend = 0;
6891                         if (Input::isKeyPressed(SDLK_MINUS))
6892                             whichend = -1;
6893                         if (whichend != -1) {
6894                             participantfocus[whichdialogue][indialogue] = whichend;
6895                             participantlocation[whichdialogue][whichend] = Person::players[whichend]->coords;
6896                             participantyaw[whichdialogue][whichend] = Person::players[whichend]->yaw;
6897                         }
6898                         if (whichend == -1) {
6899                             participantfocus[whichdialogue][indialogue] = -1;
6900                         }
6901                         if (Person::players[participantfocus[whichdialogue][indialogue]]->dead) {
6902                             indialogue = -1;
6903                             directing = 0;
6904                             cameramode = 0;
6905                         }
6906                         dialoguecamera[whichdialogue][indialogue] = viewer;
6907                         dialoguecamerayaw[whichdialogue][indialogue] = yaw;
6908                         dialoguecamerapitch[whichdialogue][indialogue] = pitch;
6909                         indialogue++;
6910                         if (indialogue < numdialogueboxes[whichdialogue]) {
6911                             if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6912                                 playdialogueboxsound();
6913                             }
6914                         }
6915
6916                         for (int j = 0; j < numplayers; j++) {
6917                             participantfacing[whichdialogue][indialogue][j] = participantfacing[whichdialogue][indialogue - 1][j];
6918                         }
6919                     }
6920                     //TODO: should these be KeyDown or KeyPressed?
6921                     if (     Input::isKeyDown(SDLK_KP1) ||
6922                              Input::isKeyDown(SDLK_KP2) ||
6923                              Input::isKeyDown(SDLK_KP3) ||
6924                              Input::isKeyDown(SDLK_KP4) ||
6925                              Input::isKeyDown(SDLK_KP5) ||
6926                              Input::isKeyDown(SDLK_KP6) ||
6927                              Input::isKeyDown(SDLK_KP7) ||
6928                              Input::isKeyDown(SDLK_KP8) ||
6929                              Input::isKeyDown(SDLK_KP9) ||
6930                              Input::isKeyDown(SDLK_KP0)) {
6931                         int whichend;
6932                         if (Input::isKeyDown(SDLK_KP1)) whichend = 1;
6933                         if (Input::isKeyDown(SDLK_KP2)) whichend = 2;
6934                         if (Input::isKeyDown(SDLK_KP3)) whichend = 3;
6935                         if (Input::isKeyDown(SDLK_KP4)) whichend = 4;
6936                         if (Input::isKeyDown(SDLK_KP5)) whichend = 5;
6937                         if (Input::isKeyDown(SDLK_KP6)) whichend = 6;
6938                         if (Input::isKeyDown(SDLK_KP7)) whichend = 7;
6939                         if (Input::isKeyDown(SDLK_KP8)) whichend = 8;
6940                         if (Input::isKeyDown(SDLK_KP9)) whichend = 9;
6941                         if (Input::isKeyDown(SDLK_KP0)) whichend = 0;
6942                         participantfacing[whichdialogue][indialogue][whichend] = facing;
6943                     }
6944                     if (indialogue >= numdialogueboxes[whichdialogue]) {
6945                         indialogue = -1;
6946                         directing = 0;
6947                         cameramode = 0;
6948                     }
6949                 }
6950                 if (!directing) {
6951                     pause_sound(whooshsound);
6952                     viewer = dialoguecamera[whichdialogue][indialogue];
6953                     viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .1);
6954                     yaw = dialoguecamerayaw[whichdialogue][indialogue];
6955                     pitch = dialoguecamerapitch[whichdialogue][indialogue];
6956                     if (dialoguetime > 0.5)
6957                         if (     Input::isKeyPressed(SDLK_1) ||
6958                                  Input::isKeyPressed(SDLK_2) ||
6959                                  Input::isKeyPressed(SDLK_3) ||
6960                                  Input::isKeyPressed(SDLK_4) ||
6961                                  Input::isKeyPressed(SDLK_5) ||
6962                                  Input::isKeyPressed(SDLK_6) ||
6963                                  Input::isKeyPressed(SDLK_7) ||
6964                                  Input::isKeyPressed(SDLK_8) ||
6965                                  Input::isKeyPressed(SDLK_9) ||
6966                                  Input::isKeyPressed(SDLK_0) ||
6967                                  Input::isKeyPressed(SDLK_MINUS) ||
6968                                  Input::isKeyPressed(attackkey)) {
6969                             indialogue++;
6970                             if (indialogue < numdialogueboxes[whichdialogue]) {
6971                                 if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6972                                     playdialogueboxsound();
6973                                     if (dialogueboxsound[whichdialogue][indialogue] == -5) {
6974                                         hotspot[numhotspots] = Person::players[0]->coords;
6975                                         hotspotsize[numhotspots] = 10;
6976                                         hotspottype[numhotspots] = -1;
6977
6978                                         numhotspots++;
6979                                     }
6980                                     if (dialogueboxsound[whichdialogue][indialogue] == -6) {
6981                                         hostile = 1;
6982                                     }
6983
6984                                     if (Person::players[participantfocus[whichdialogue][indialogue]]->dead) {
6985                                         indialogue = -1;
6986                                         directing = 0;
6987                                         cameramode = 0;
6988                                     }
6989                                 }
6990                             }
6991                         }
6992                     if (indialogue >= numdialogueboxes[whichdialogue]) {
6993                         indialogue = -1;
6994                         directing = 0;
6995                         cameramode = 0;
6996                         if (dialoguetype[whichdialogue] > 19 && dialoguetype[whichdialogue] < 30) {
6997                             hostile = 1;
6998                         }
6999                         if (dialoguetype[whichdialogue] > 29 && dialoguetype[whichdialogue] < 40) {
7000                             windialogue = true;
7001                         }
7002                         if (dialoguetype[whichdialogue] > 49 && dialoguetype[whichdialogue] < 60) {
7003                             hostile = 1;
7004                             for (int i = 1; i < numplayers; i++) {
7005                                 Person::players[i]->aitype = attacktypecutoff;
7006                             }
7007                         }
7008                     }
7009                 }
7010             }
7011
7012             if (!Person::players[0]->jumpkeydown) {
7013                 Person::players[0]->jumptogglekeydown = 0;
7014             }
7015             if (Person::players[0]->jumpkeydown &&
7016                     Person::players[0]->animTarget != jumpupanim &&
7017                     Person::players[0]->animTarget != jumpdownanim &&
7018                     !Person::players[0]->isFlip())
7019                 Person::players[0]->jumptogglekeydown = 1;
7020
7021
7022             dialoguetime += multiplier;
7023             hawkyaw += multiplier * 25;
7024             realhawkcoords = 0;
7025             realhawkcoords.x = 25;
7026             realhawkcoords = DoRotation(realhawkcoords, 0, hawkyaw, 0) + hawkcoords;
7027             hawkcalldelay -= multiplier / 2;
7028
7029             if (hawkcalldelay <= 0) {
7030                 emit_sound_at(hawksound, realhawkcoords);
7031
7032                 hawkcalldelay = 16 + abs(Random() % 8);
7033             }
7034
7035             doDebugKeys();
7036
7037             doAttacks();
7038
7039             doPlayerCollisions();
7040
7041             doJumpReversals();
7042
7043             for (int k = 0; k < numplayers; k++)
7044                 if (k != 0 && Person::players[k]->immobile)
7045                     Person::players[k]->coords = Person::players[k]->realoldcoords;
7046
7047             for (int k = 0; k < numplayers; k++) {
7048                 if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
7049                     if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
7050                         Person::players[k]->DoDamage(1000);
7051                     }
7052                 }
7053             }
7054
7055             //respawn
7056             static bool respawnkeydown;
7057             if (!editorenabled &&
7058                     (whichlevel != -2 &&
7059                      (Input::isKeyDown(SDLK_z) &&
7060                       Input::isKeyDown(SDLK_LMETA) &&
7061                       debugmode) ||
7062                      (Input::isKeyDown(jumpkey) &&
7063                       !respawnkeydown &&
7064                       !oldattackkey &&
7065                       Person::players[0]->dead))) {
7066                 targetlevel = whichlevel;
7067                 loading = 1;
7068                 leveltime = 5;
7069             }
7070             if (!Input::isKeyDown(jumpkey))
7071                 respawnkeydown = 0;
7072             if (Input::isKeyDown(jumpkey))
7073                 respawnkeydown = 1;
7074
7075
7076
7077
7078             static bool movekey;
7079
7080             //?
7081             for (int i = 0; i < numplayers; i++) {
7082                 static float oldtargetyaw;
7083                 if (!Person::players[i]->skeleton.free) {
7084                     oldtargetyaw = Person::players[i]->targetyaw;
7085                     if (i == 0 && indialogue == -1) {
7086                         //TODO: refactor repetitive code
7087                         if (!animation[Person::players[0]->animTarget].attack &&
7088                                 Person::players[0]->animTarget != staggerbackhighanim &&
7089                                 Person::players[0]->animTarget != staggerbackhardanim &&
7090                                 Person::players[0]->animTarget != crouchremoveknifeanim &&
7091                                 Person::players[0]->animTarget != removeknifeanim &&
7092                                 Person::players[0]->animTarget != backhandspringanim &&
7093                                 Person::players[0]->animTarget != dodgebackanim &&
7094                                 Person::players[0]->animTarget != walljumprightkickanim &&
7095                                 Person::players[0]->animTarget != walljumpleftkickanim) {
7096                             if (cameramode)
7097                                 Person::players[0]->targetyaw = 0;
7098                             else
7099                                 Person::players[0]->targetyaw = -yaw + 180;
7100                         }
7101
7102                         facing = 0;
7103                         facing.z = -1;
7104
7105                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
7106                         if (cameramode) {
7107                             facing = flatfacing;
7108                         } else {
7109                             facing = DoRotation(facing, -pitch, 0, 0);
7110                             facing = DoRotation(facing, 0, 0 - yaw, 0);
7111                         }
7112
7113                         Person::players[0]->lookyaw = -yaw;
7114
7115                         Person::players[i]->targetheadyaw = yaw;
7116                         Person::players[i]->targetheadpitch = pitch;
7117                     }
7118                     if (i != 0 && Person::players[i]->aitype == playercontrolled && indialogue == -1) {
7119                         if (!animation[Person::players[i]->animTarget].attack &&
7120                                 Person::players[i]->animTarget != staggerbackhighanim &&
7121                                 Person::players[i]->animTarget != staggerbackhardanim &&
7122                                 Person::players[i]->animTarget != crouchremoveknifeanim &&
7123                                 Person::players[i]->animTarget != removeknifeanim &&
7124                                 Person::players[i]->animTarget != backhandspringanim &&
7125                                 Person::players[i]->animTarget != dodgebackanim &&
7126                                 Person::players[i]->animTarget != walljumprightkickanim &&
7127                                 Person::players[i]->animTarget != walljumpleftkickanim) {
7128                             Person::players[i]->targetyaw = -Person::players[i]->lookyaw + 180;
7129                         }
7130
7131                         facing = 0;
7132                         facing.z = -1;
7133
7134                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
7135
7136                         facing = DoRotation(facing, -Person::players[i]->lookpitch, 0, 0);
7137                         facing = DoRotation(facing, 0, 0 - Person::players[i]->lookyaw, 0);
7138
7139                         Person::players[i]->targetheadyaw = Person::players[i]->lookyaw;
7140                         Person::players[i]->targetheadpitch = Person::players[i]->lookpitch;
7141                     }
7142                     if (indialogue != -1) {
7143                         Person::players[i]->targetheadyaw = 180 - roughDirection(participantfacing[whichdialogue][indialogue][i]);
7144                         Person::players[i]->targetheadpitch = pitchOf(participantfacing[whichdialogue][indialogue][i]);
7145                     }
7146
7147                     if (leveltime < .5)
7148                         numenvsounds = 0;
7149
7150                     Person::players[i]->avoidsomething = 0;
7151
7152                     //avoid flaming things
7153                     for (int j = 0; j < objects.numobjects; j++)
7154                         if (objects.onfire[j])
7155                             if (distsq(&Person::players[i]->coords, &objects.position[j]) < sq(objects.scale[j]) * 200)
7156                                 if (     distsq(&Person::players[i]->coords, &objects.position[j]) <
7157                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
7158                                     Person::players[i]->collided = 0;
7159                                     Person::players[i]->avoidcollided = 1;
7160                                     if (Person::players[i]->avoidsomething == 0 ||
7161                                             distsq(&Person::players[i]->coords, &objects.position[j]) <
7162                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
7163                                         Person::players[i]->avoidwhere = objects.position[j];
7164                                         Person::players[i]->avoidsomething = 1;
7165                                     }
7166                                 }
7167
7168                     //avoid flaming players
7169                     for (int j = 0; j < numplayers; j++)
7170                         if (Person::players[j]->onfire)
7171                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < sq(0.3) * 200)
7172                                 if (     distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
7173                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
7174                                     Person::players[i]->collided = 0;
7175                                     Person::players[i]->avoidcollided = 1;
7176                                     if (Person::players[i]->avoidsomething == 0 ||
7177                                             distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
7178                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
7179                                         Person::players[i]->avoidwhere = Person::players[j]->coords;
7180                                         Person::players[i]->avoidsomething = 1;
7181                                     }
7182                                 }
7183
7184                     if (Person::players[i]->collided > .8)
7185                         Person::players[i]->avoidcollided = 0;
7186
7187                     doAI(i);
7188
7189                     if (animation[Person::players[i]->animTarget].attack == reversed) {
7190                         //Person::players[i]->targetyaw=Person::players[i]->yaw;
7191                         Person::players[i]->forwardkeydown = 0;
7192                         Person::players[i]->leftkeydown = 0;
7193                         Person::players[i]->backkeydown = 0;
7194                         Person::players[i]->rightkeydown = 0;
7195                         Person::players[i]->jumpkeydown = 0;
7196                         Person::players[i]->attackkeydown = 0;
7197                         //Person::players[i]->crouchkeydown=0;
7198                         Person::players[i]->throwkeydown = 0;
7199                     }
7200
7201                     if (indialogue != -1) {
7202                         Person::players[i]->forwardkeydown = 0;
7203                         Person::players[i]->leftkeydown = 0;
7204                         Person::players[i]->backkeydown = 0;
7205                         Person::players[i]->rightkeydown = 0;
7206                         Person::players[i]->jumpkeydown = 0;
7207                         Person::players[i]->crouchkeydown = 0;
7208                         Person::players[i]->drawkeydown = 0;
7209                         Person::players[i]->throwkeydown = 0;
7210                     }
7211
7212                     if (Person::players[i]->collided < -.3)
7213                         Person::players[i]->collided = -.3;
7214                     if (Person::players[i]->collided > 1)
7215                         Person::players[i]->collided = 1;
7216                     Person::players[i]->collided -= multiplier * 4;
7217                     Person::players[i]->whichdirectiondelay -= multiplier;
7218                     if (Person::players[i]->avoidcollided < -.3 || Person::players[i]->whichdirectiondelay <= 0) {
7219                         Person::players[i]->avoidcollided = -.3;
7220                         Person::players[i]->whichdirection = abs(Random() % 2);
7221                         Person::players[i]->whichdirectiondelay = .4;
7222                     }
7223                     if (Person::players[i]->avoidcollided > 1)
7224                         Person::players[i]->avoidcollided = 1;
7225                     Person::players[i]->avoidcollided -= multiplier / 4;
7226                     if (!Person::players[i]->skeleton.free) {
7227                         Person::players[i]->stunned -= multiplier;
7228                         Person::players[i]->surprised -= multiplier;
7229                     }
7230                     if (i != 0 && Person::players[i]->surprised <= 0 &&
7231                             Person::players[i]->aitype == attacktypecutoff &&
7232                             !Person::players[i]->dead &&
7233                             !Person::players[i]->skeleton.free &&
7234                             animation[Person::players[i]->animTarget].attack == neutral)
7235                         numresponded = 1;
7236
7237                     if (!Person::players[i]->throwkeydown)
7238                         Person::players[i]->throwtogglekeydown = 0;
7239
7240                     //pick up weapon
7241                     if (Person::players[i]->throwkeydown && !Person::players[i]->throwtogglekeydown) {
7242                         if (Person::players[i]->weaponactive == -1 &&
7243                                 Person::players[i]->num_weapons < 2 &&
7244                                 (Person::players[i]->isIdle() ||
7245                                  Person::players[i]->isCrouch() ||
7246                                  Person::players[i]->animTarget == sneakanim ||
7247                                  Person::players[i]->animTarget == rollanim ||
7248                                  Person::players[i]->animTarget == backhandspringanim ||
7249                                  Person::players[i]->isFlip() ||
7250                                  Person::players[i]->isFlip() ||
7251                                  Person::players[i]->aitype != playercontrolled)) {
7252                             for (int j = 0; j < weapons.size(); j++) {
7253                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
7254                                         Person::players[i]->aitype == playercontrolled) &&
7255                                         weapons[j].owner == -1 &&
7256                                         Person::players[i]->weaponactive == -1)
7257                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2) {
7258                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 2) {
7259                                             if (Person::players[i]->isCrouch() ||
7260                                                     Person::players[i]->animTarget == sneakanim ||
7261                                                     Person::players[i]->isRun() ||
7262                                                     Person::players[i]->isIdle() ||
7263                                                     Person::players[i]->aitype != playercontrolled) {
7264                                                 Person::players[i]->throwtogglekeydown = 1;
7265                                                 Person::players[i]->setAnimation(crouchremoveknifeanim);
7266                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
7267                                                 Person::players[i]->hasvictim = 0;
7268                                             }
7269                                             if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
7270                                                 Person::players[i]->throwtogglekeydown = 1;
7271                                                 Person::players[i]->hasvictim = 0;
7272
7273                                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
7274                                                         Person::players[i]->aitype == playercontrolled) &&
7275                                                         weapons[j].owner == -1 ||
7276                                                         Person::players[i]->victim &&
7277                                                         weapons[j].owner == Person::players[i]->victim->id)
7278                                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2 && Person::players[i]->weaponactive == -1)
7279                                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 1 || Person::players[i]->victim) {
7280                                                             if (weapons[j].getType() != staff)
7281                                                                 emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
7282
7283                                                             Person::players[i]->weaponactive = 0;
7284                                                             weapons[j].owner = Person::players[i]->id;
7285                                                             if (Person::players[i]->num_weapons > 0)
7286                                                                 Person::players[i]->weaponids[Person::players[i]->num_weapons] = Person::players[i]->weaponids[0];
7287                                                             Person::players[i]->num_weapons++;
7288                                                             Person::players[i]->weaponids[0] = j;
7289                                                         }
7290                                             }
7291                                         } else if ((Person::players[i]->isIdle() ||
7292                                                     Person::players[i]->isFlip() ||
7293                                                     Person::players[i]->aitype != playercontrolled) &&
7294                                                    distsq(&Person::players[i]->coords, &weapons[j].position) < 5 &&
7295                                                    Person::players[i]->coords.y < weapons[j].position.y) {
7296                                             if (!Person::players[i]->isFlip()) {
7297                                                 Person::players[i]->throwtogglekeydown = 1;
7298                                                 Person::players[i]->setAnimation(removeknifeanim);
7299                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
7300                                             }
7301                                             if (Person::players[i]->isFlip()) {
7302                                                 Person::players[i]->throwtogglekeydown = 1;
7303                                                 Person::players[i]->hasvictim = 0;
7304
7305                                                 for (int k = 0; k < weapons.size(); k++) {
7306                                                     if (Person::players[i]->weaponactive == -1)
7307                                                         if ((weapons[k].velocity.x == 0 && weapons[k].velocity.y == 0 && weapons[k].velocity.z == 0 ||
7308                                                                 Person::players[i]->aitype == playercontrolled) &&
7309                                                                 weapons[k].owner == -1 ||
7310                                                                 Person::players[i]->victim &&
7311                                                                 weapons[k].owner == Person::players[i]->victim->id)
7312                                                             if (distsqflat(&Person::players[i]->coords, &weapons[k].position) < 3 &&
7313                                                                     Person::players[i]->weaponactive == -1) {
7314                                                                 if (weapons[k].getType() != staff)
7315                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
7316
7317                                                                 Person::players[i]->weaponactive = 0;
7318                                                                 weapons[k].owner = Person::players[i]->id;
7319                                                                 if (Person::players[i]->num_weapons > 0)
7320                                                                     Person::players[i]->weaponids[Person::players[i]->num_weapons] = Person::players[i]->weaponids[0];
7321                                                                 Person::players[i]->num_weapons++;
7322                                                                 Person::players[i]->weaponids[0] = k;
7323                                                             }
7324                                                 }
7325                                             }
7326                                         }
7327                                     }
7328                             }
7329                             if (Person::players[i]->isCrouch() ||
7330                                     Person::players[i]->animTarget == sneakanim ||
7331                                     Person::players[i]->isRun() ||
7332                                     Person::players[i]->isIdle() || Person::players[i]->animTarget == rollanim ||
7333                                     Person::players[i]->animTarget == backhandspringanim) {
7334                                 if (numplayers > 1)
7335                                     for (int j = 0; j < numplayers; j++) {
7336                                         if (Person::players[i]->weaponactive == -1)
7337                                             if (j != i)
7338                                                 if (Person::players[j]->num_weapons &&
7339                                                         Person::players[j]->skeleton.free &&
7340                                                         distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 2/*&&Person::players[j]->dead*/ &&
7341                                                         (((Person::players[j]->skeleton.forward.y < 0 &&
7342                                                            Person::players[j]->weaponstuckwhere == 0) ||
7343                                                           (Person::players[j]->skeleton.forward.y > 0 &&
7344                                                            Person::players[j]->weaponstuckwhere == 1)) ||
7345                                                          Person::players[j]->weaponstuck == -1 ||
7346                                                          Person::players[j]->num_weapons > 1)) {
7347                                                     if (Person::players[i]->animTarget != rollanim && Person::players[i]->animTarget != backhandspringanim) {
7348                                                         Person::players[i]->throwtogglekeydown = 1;
7349                                                         Person::players[i]->victim = Person::players[j];
7350                                                         Person::players[i]->hasvictim = 1;
7351                                                         Person::players[i]->setAnimation(crouchremoveknifeanim);
7352                                                         Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
7353                                                     }
7354                                                     if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
7355                                                         Person::players[i]->throwtogglekeydown = 1;
7356                                                         Person::players[i]->victim = Person::players[j];
7357                                                         Person::players[i]->hasvictim = 1;
7358                                                         int k = Person::players[j]->weaponids[0];
7359                                                         if (Person::players[i]->hasvictim) {
7360                                                             bool fleshstuck;
7361                                                             fleshstuck = 0;
7362                                                             if (Person::players[i]->victim->weaponstuck != -1) {
7363                                                                 if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
7364                                                                     fleshstuck = 1;
7365                                                                 }
7366                                                             }
7367                                                             if (!fleshstuck) {
7368                                                                 if (weapons[k].getType() != staff)
7369                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
7370                                                             }
7371                                                             if (fleshstuck)
7372                                                                 emit_sound_at(fleshstabremovesound, Person::players[i]->coords, 128.);
7373
7374                                                             Person::players[i]->weaponactive = 0;
7375                                                             if (weapons[k].owner != -1) {
7376                                                                 if (Person::players[i]->victim->num_weapons == 1)
7377                                                                     Person::players[i]->victim->num_weapons = 0;
7378                                                                 else
7379                                                                     Person::players[i]->victim->num_weapons = 1;
7380
7381                                                                 Person::players[i]->victim->skeleton.longdead = 0;
7382                                                                 Person::players[i]->victim->skeleton.free = 1;
7383                                                                 Person::players[i]->victim->skeleton.broken = 0;
7384
7385                                                                 for (int l = 0; l < Person::players[i]->victim->skeleton.num_joints; l++) {
7386                                                                     Person::players[i]->victim->skeleton.joints[l].velchange = 0;
7387                                                                     Person::players[i]->victim->skeleton.joints[l].locked = 0;
7388                                                                 }
7389
7390                                                                 XYZ relative;
7391                                                                 relative = 0;
7392                                                                 relative.y = 10;
7393                                                                 Normalise(&relative);
7394                                                                 XYZ footvel, footpoint;
7395                                                                 footvel = 0;
7396                                                                 footpoint = weapons[k].position;
7397                                                                 if (Person::players[i]->victim->weaponstuck != -1) {
7398                                                                     if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
7399                                                                         if (bloodtoggle)
7400                                                                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
7401                                                                         weapons[k].bloody = 2;
7402                                                                         weapons[k].blooddrip = 5;
7403                                                                         Person::players[i]->victim->weaponstuck = -1;
7404                                                                         Person::players[i]->victim->bloodloss += 2000;
7405                                                                         Person::players[i]->victim->DoDamage(2000);
7406                                                                     }
7407                                                                 }
7408                                                                 if (Person::players[i]->victim->num_weapons > 0) {
7409                                                                     if (Person::players[i]->victim->weaponstuck != 0 && Person::players[i]->victim->weaponstuck != -1)
7410                                                                         Person::players[i]->victim->weaponstuck = 0;
7411                                                                     if (Person::players[i]->victim->weaponids[0] == k)
7412                                                                         Person::players[i]->victim->weaponids[0] = Person::players[i]->victim->weaponids[Person::players[i]->victim->num_weapons];
7413                                                                 }
7414
7415                                                                 Person::players[i]->victim->weaponactive = -1;
7416
7417                                                                 Person::players[i]->victim->jointVel(abdomen) += relative * 6;
7418                                                                 Person::players[i]->victim->jointVel(neck) += relative * 6;
7419                                                                 Person::players[i]->victim->jointVel(rightshoulder) += relative * 6;
7420                                                                 Person::players[i]->victim->jointVel(leftshoulder) += relative * 6;
7421                                                             }
7422                                                             weapons[k].owner = i;
7423                                                             if (Person::players[i]->num_weapons > 0) {
7424                                                                 Person::players[i]->weaponids[Person::players[i]->num_weapons] = Person::players[i]->weaponids[0];
7425                                                             }
7426                                                             Person::players[i]->num_weapons++;
7427                                                             Person::players[i]->weaponids[0] = k;
7428                                                         }
7429                                                     }
7430                                                 }
7431                                     }
7432                             }
7433                         }
7434                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
7435                             if (weapons[Person::players[i]->weaponids[0]].getType() == knife) {
7436                                 if (Person::players[i]->isIdle() ||
7437                                         Person::players[i]->isRun() ||
7438                                         Person::players[i]->isCrouch() ||
7439                                         Person::players[i]->animTarget == sneakanim ||
7440                                         Person::players[i]->isFlip())
7441                                     if (numplayers > 1)
7442                                         for (int j = 0; j < numplayers; j++) {
7443                                             if (i != j)
7444                                                 if (tutoriallevel != 1 || tutorialstage == 49)
7445                                                     if (hostile)
7446                                                         if (normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0 &&
7447                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 100 &&
7448                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) > 1.5 &&
7449                                                                 !Person::players[j]->skeleton.free &&
7450                                                                 -1 == checkcollide(DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*Person::players[j]->scale + Person::players[j]->coords, DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)*Person::players[i]->scale + Person::players[i]->coords)) {
7451                                                             if (!Person::players[i]->isFlip()) {
7452                                                                 Person::players[i]->throwtogglekeydown = 1;
7453                                                                 Person::players[i]->victim = Person::players[j];
7454                                                                 Person::players[i]->setAnimation(knifethrowanim);
7455                                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
7456                                                                 Person::players[i]->targettilt2 = pitchTo(Person::players[i]->coords, Person::players[j]->coords);
7457                                                             }
7458                                                             if (Person::players[i]->isFlip()) {
7459                                                                 if (Person::players[i]->weaponactive != -1) {
7460                                                                     Person::players[i]->throwtogglekeydown = 1;
7461                                                                     Person::players[i]->victim = Person::players[j];
7462                                                                     XYZ aim;
7463                                                                     weapons[Person::players[i]->weaponids[0]].owner = -1;
7464                                                                     aim = Person::players[i]->victim->coords + DoRotation(Person::players[i]->victim->jointPos(abdomen), 0, Person::players[i]->victim->yaw, 0) * Person::players[i]->victim->scale + Person::players[i]->victim->velocity * findDistance(&Person::players[i]->victim->coords, &Person::players[i]->coords) / 50 - (Person::players[i]->coords + DoRotation(Person::players[i]->jointPos(righthand), 0, Person::players[i]->yaw, 0) * Person::players[i]->scale);
7465                                                                     Normalise(&aim);
7466
7467                                                                     aim = DoRotation(aim, (float)abs(Random() % 30) - 15, (float)abs(Random() % 30) - 15, 0);
7468
7469                                                                     weapons[Person::players[i]->weaponids[0]].velocity = aim * 50;
7470                                                                     weapons[Person::players[i]->weaponids[0]].tipvelocity = aim * 50;
7471                                                                     weapons[Person::players[i]->weaponids[0]].missed = 0;
7472                                                                     weapons[Person::players[i]->weaponids[0]].freetime = 0;
7473                                                                     weapons[Person::players[i]->weaponids[0]].firstfree = 1;
7474                                                                     weapons[Person::players[i]->weaponids[0]].physics = 0;
7475                                                                     Person::players[i]->num_weapons--;
7476                                                                     if (Person::players[i]->num_weapons) {
7477                                                                         Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
7478                                                                     }
7479                                                                     Person::players[i]->weaponactive = -1;
7480                                                                 }
7481                                                             }
7482                                                         }
7483                                         }
7484                             }
7485                         }
7486                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
7487                             if (Person::players[i]->isCrouch() || Person::players[i]->animTarget == sneakanim) {
7488                                 Person::players[i]->throwtogglekeydown = 1;
7489                                 weapons[Person::players[i]->weaponids[0]].owner = -1;
7490                                 weapons[Person::players[i]->weaponids[0]].velocity = Person::players[i]->velocity * .2;
7491                                 if (weapons[Person::players[i]->weaponids[0]].velocity.x == 0)
7492                                     weapons[Person::players[i]->weaponids[0]].velocity.x = .1;
7493                                 weapons[Person::players[i]->weaponids[0]].tipvelocity = weapons[Person::players[i]->weaponids[0]].velocity;
7494                                 weapons[Person::players[i]->weaponids[0]].missed = 1;
7495                                 weapons[Person::players[i]->weaponids[0]].freetime = 0;
7496                                 weapons[Person::players[i]->weaponids[0]].firstfree = 1;
7497                                 weapons[Person::players[i]->weaponids[0]].physics = 1;
7498                                 Person::players[i]->num_weapons--;
7499                                 if (Person::players[i]->num_weapons) {
7500                                     Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
7501                                     if (Person::players[i]->weaponstuck == Person::players[i]->num_weapons)
7502                                         Person::players[i]->weaponstuck = 0;
7503                                 }
7504
7505                                 Person::players[i]->weaponactive = -1;
7506                                 for (int j = 0; j < numplayers; j++) {
7507                                     Person::players[j]->wentforweapon = 0;
7508                                 }
7509                             }
7510                         }
7511
7512                     }
7513
7514                     //draw weapon
7515                     if (i == 0 || !Person::players[0]->dead || (Person::players[i]->weaponactive != -1)) {
7516                         if (Person::players[i]->drawkeydown && !Person::players[i]->drawtogglekeydown ||
7517                                 (Person::players[i]->num_weapons == 2) &&
7518                                 (Person::players[i]->weaponactive == -1) &&
7519                                 Person::players[i]->isIdle() ||
7520                                 Person::players[0]->dead &&
7521                                 (Person::players[i]->weaponactive != -1) &&
7522                                 i != 0) {
7523                             bool isgood = true;
7524                             if (Person::players[i]->weaponactive != -1)
7525                                 if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == staff)
7526                                     isgood = false;
7527                             if (isgood && Person::players[i]->creature != wolftype) {
7528                                 if (Person::players[i]->isIdle() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
7529                                     Person::players[i]->setAnimation(drawrightanim);
7530                                     Person::players[i]->drawtogglekeydown = 1;
7531                                 }
7532                                 if ((Person::players[i]->isIdle() ||
7533                                         (Person::players[i]->aitype != playercontrolled &&
7534                                          Person::players[0]->weaponactive != -1 &&
7535                                          Person::players[i]->isRun())) &&
7536                                         Person::players[i]->num_weapons &&
7537                                         weapons[Person::players[i]->weaponids[0]].getType() == sword) {
7538                                     Person::players[i]->setAnimation(drawleftanim);
7539                                     Person::players[i]->drawtogglekeydown = 1;
7540                                 }
7541                                 if (Person::players[i]->isCrouch() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
7542                                     Person::players[i]->setAnimation(crouchdrawrightanim);
7543                                     Person::players[i]->drawtogglekeydown = 1;
7544                                 }
7545                             }
7546                         }
7547                     }
7548
7549                     //clean weapon
7550                     if (Person::players[i]->weaponactive != -1) {
7551                         if (Person::players[i]->isCrouch() &&
7552                                 weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].bloody &&
7553                                 bloodtoggle &&
7554                                 Person::players[i]->onterrain &&
7555                                 Person::players[i]->num_weapons &&
7556                                 Person::players[i]->attackkeydown &&
7557                                 musictype != stream_fighttheme) {
7558                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == knife)
7559                                 Person::players[i]->setAnimation(crouchstabanim);
7560                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == sword)
7561                                 Person::players[i]->setAnimation(swordgroundstabanim);
7562                             Person::players[i]->hasvictim = 0;
7563                         }
7564                     }
7565
7566                     if (!Person::players[i]->drawkeydown)
7567                         Person::players[i]->drawtogglekeydown = 0;
7568
7569                     XYZ absflatfacing;
7570                     if (i == 0) {
7571                         absflatfacing = 0;
7572                         absflatfacing.z = -1;
7573
7574                         absflatfacing = DoRotation(absflatfacing, 0, -yaw, 0);
7575                     } else
7576                         absflatfacing = flatfacing;
7577
7578                     if (indialogue != -1) {
7579                         Person::players[i]->forwardkeydown = 0;
7580                         Person::players[i]->leftkeydown = 0;
7581                         Person::players[i]->backkeydown = 0;
7582                         Person::players[i]->rightkeydown = 0;
7583                         Person::players[i]->jumpkeydown = 0;
7584                         Person::players[i]->crouchkeydown = 0;
7585                         Person::players[i]->drawkeydown = 0;
7586                         Person::players[i]->throwkeydown = 0;
7587                     }
7588                     movekey = 0;
7589                     //Do controls
7590                     if (!animation[Person::players[i]->animTarget].attack &&
7591                             Person::players[i]->animTarget != staggerbackhighanim &&
7592                             Person::players[i]->animTarget != staggerbackhardanim &&
7593                             Person::players[i]->animTarget != backhandspringanim &&
7594                             Person::players[i]->animTarget != dodgebackanim) {
7595                         if (!Person::players[i]->forwardkeydown)
7596                             Person::players[i]->forwardstogglekeydown = 0;
7597                         if (Person::players[i]->crouchkeydown) {
7598                             //Crouch
7599                             target = -2;
7600                             if (i == 0) {
7601                                 Person::players[i]->superruntoggle = 1;
7602                                 if (numplayers > 1)
7603                                     for (int j = 0; j < numplayers; j++)
7604                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->aitype == passivetype)
7605                                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 16)
7606                                                 Person::players[i]->superruntoggle = 0;
7607                             }
7608
7609                             if (numplayers > 1)
7610                                 for (int j = 0; j < numplayers; j++) {
7611                                     if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim && Person::players[i]->lowreversaldelay <= 0) {
7612                                         if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
7613                                                 Person::players[j]->victim == Person::players[i] &&
7614                                                 (Person::players[j]->animTarget == sweepanim ||
7615                                                  Person::players[j]->animTarget == upunchanim ||
7616                                                  Person::players[j]->animTarget == wolfslapanim ||
7617                                                  ((Person::players[j]->animTarget == swordslashanim ||
7618                                                    Person::players[j]->animTarget == knifeslashstartanim ||
7619                                                    Person::players[j]->animTarget == staffhitanim ||
7620                                                    Person::players[j]->animTarget == staffspinhitanim) &&
7621                                                   distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2))) {
7622                                             if (target >= 0)
7623                                                 target = -1;
7624                                             else
7625                                                 target = j;
7626                                         }
7627                                     }
7628                                 }
7629                             if (target >= 0)
7630                                 Person::players[target]->Reverse();
7631                             Person::players[i]->lowreversaldelay = .5;
7632
7633                             if (Person::players[i]->isIdle()) {
7634                                 Person::players[i]->setAnimation(Person::players[i]->getCrouch());
7635                                 Person::players[i]->transspeed = 10;
7636                             }
7637                             if (Person::players[i]->isRun() ||
7638                                     (Person::players[i]->isStop() &&
7639                                      (Person::players[i]->leftkeydown ||
7640                                       Person::players[i]->rightkeydown ||
7641                                       Person::players[i]->forwardkeydown ||
7642                                       Person::players[i]->backkeydown))) {
7643                                 Person::players[i]->setAnimation(rollanim);
7644                                 Person::players[i]->transspeed = 20;
7645                             }
7646                         }
7647                         if (!Person::players[i]->crouchkeydown) {
7648                             //Uncrouch
7649                             if (!Person::players[i]->isRun() && Person::players[i]->animTarget != sneakanim && i == 0)
7650                                 Person::players[i]->superruntoggle = 0;
7651                             target = -2;
7652                             if (Person::players[i]->isCrouch()) {
7653                                 if (numplayers > 1)
7654                                     for (int j = 0; j < numplayers; j++) {
7655                                         if (j != i &&
7656                                                 !Person::players[j]->skeleton.free &&
7657                                                 Person::players[j]->victim &&
7658                                                 Person::players[i]->highreversaldelay <= 0) {
7659                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
7660                                                     Person::players[j]->victim == Person::players[i] &&
7661                                                     (Person::players[j]->animTarget == spinkickanim) &&
7662                                                     Person::players[i]->isCrouch()) {
7663                                                 if (target >= 0)
7664                                                     target = -1;
7665                                                 else
7666                                                     target = j;
7667                                             }
7668                                         }
7669                                     }
7670                                 if (target >= 0)
7671                                     Person::players[target]->Reverse();
7672                                 Person::players[i]->highreversaldelay = .5;
7673
7674                                 if (Person::players[i]->isCrouch()) {
7675                                     if (!Person::players[i]->wasCrouch()) {
7676                                         Person::players[i]->animCurrent = Person::players[i]->getCrouch();
7677                                         Person::players[i]->frameCurrent = 0;
7678                                     }
7679                                     Person::players[i]->setAnimation(Person::players[i]->getIdle());
7680                                     Person::players[i]->transspeed = 10;
7681                                 }
7682                             }
7683                             if (Person::players[i]->animTarget == sneakanim) {
7684                                 Person::players[i]->setAnimation(Person::players[i]->getIdle());
7685                                 Person::players[i]->transspeed = 10;
7686                             }
7687                         }
7688                         if (Person::players[i]->forwardkeydown) {
7689                             if (Person::players[i]->isIdle() ||
7690                                     (Person::players[i]->isStop() &&
7691                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
7692                                     (Person::players[i]->isLanding() &&
7693                                      Person::players[i]->frameTarget > 0 &&
7694                                      !Person::players[i]->jumpkeydown) ||
7695                                     (Person::players[i]->isLandhard() &&
7696                                      Person::players[i]->frameTarget > 0 &&
7697                                      !Person::players[i]->jumpkeydown &&
7698                                      Person::players[i]->crouchkeydown)) {
7699                                 if (Person::players[i]->aitype == passivetype)
7700                                     Person::players[i]->setAnimation(walkanim);
7701                                 else
7702                                     Person::players[i]->setAnimation(Person::players[i]->getRun());
7703                             }
7704                             if (Person::players[i]->isCrouch()) {
7705                                 Person::players[i]->animTarget = sneakanim;
7706                                 if (Person::players[i]->wasCrouch())
7707                                     Person::players[i]->target = 0;
7708                                 Person::players[i]->frameTarget = 0;
7709                             }
7710                             if (Person::players[i]->animTarget == hanganim/*&&(!Person::players[i]->forwardstogglekeydown||Person::players[i]->aitype!=playercontrolled)*/) {
7711                                 Person::players[i]->setAnimation(climbanim);
7712                                 Person::players[i]->frameTarget = 1;
7713                                 Person::players[i]->jumpclimb = 1;
7714                             }
7715                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
7716                                 Person::players[i]->velocity += absflatfacing * 5 * multiplier;
7717                             }
7718                             Person::players[i]->forwardstogglekeydown = 1;
7719                             movekey = 1;
7720                         }
7721                         if (Person::players[i]->rightkeydown) {
7722                             if (Person::players[i]->isIdle() ||
7723                                     (Person::players[i]->isStop() &&
7724                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
7725                                     (Person::players[i]->isLanding() &&
7726                                      Person::players[i]->frameTarget > 0 &&
7727                                      !Person::players[i]->jumpkeydown) ||
7728                                     (Person::players[i]->isLandhard() &&
7729                                      Person::players[i]->frameTarget > 0 &&
7730                                      !Person::players[i]->jumpkeydown &&
7731                                      Person::players[i]->crouchkeydown)) {
7732                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
7733                             }
7734                             if (Person::players[i]->isCrouch()) {
7735                                 Person::players[i]->animTarget = sneakanim;
7736                                 if (Person::players[i]->wasCrouch())
7737                                     Person::players[i]->target = 0;
7738                                 Person::players[i]->frameTarget = 0;
7739                             }
7740                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
7741                                 Person::players[i]->velocity += DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
7742                             }
7743                             Person::players[i]->targetyaw -= 90;
7744                             if (Person::players[i]->forwardkeydown)
7745                                 Person::players[i]->targetyaw += 45;
7746                             if (Person::players[i]->backkeydown)
7747                                 Person::players[i]->targetyaw -= 45;
7748                             movekey = 1;
7749                         }
7750                         if ( Person::players[i]->leftkeydown) {
7751                             if (Person::players[i]->isIdle() ||
7752                                     (Person::players[i]->isStop() &&
7753                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
7754                                     (Person::players[i]->isLanding() &&
7755                                      Person::players[i]->frameTarget > 0 &&
7756                                      !Person::players[i]->jumpkeydown) ||
7757                                     (Person::players[i]->isLandhard() &&
7758                                      Person::players[i]->frameTarget > 0 &&
7759                                      !Person::players[i]->jumpkeydown &&
7760                                      Person::players[i]->crouchkeydown)) {
7761                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
7762                             }
7763                             if (Person::players[i]->isCrouch()) {
7764                                 Person::players[i]->animTarget = sneakanim;
7765                                 if (Person::players[i]->wasCrouch())
7766                                     Person::players[i]->target = 0;
7767                                 Person::players[i]->frameTarget = 0;
7768                             }
7769                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
7770                                 Person::players[i]->velocity -= DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
7771                             }
7772                             Person::players[i]->targetyaw += 90;
7773                             if (Person::players[i]->forwardkeydown)
7774                                 Person::players[i]->targetyaw -= 45;
7775                             if (Person::players[i]->backkeydown)
7776                                 Person::players[i]->targetyaw += 45;
7777                             movekey = 1;
7778                         }
7779                         if (Person::players[i]->backkeydown) {
7780                             if (Person::players[i]->isIdle() ||
7781                                     (Person::players[i]->isStop() &&
7782                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
7783                                     (Person::players[i]->isLanding() &&
7784                                      Person::players[i]->frameTarget > 0 &&
7785                                      !Person::players[i]->jumpkeydown) ||
7786                                     (Person::players[i]->isLandhard() &&
7787                                      Person::players[i]->frameTarget > 0 &&
7788                                      !Person::players[i]->jumpkeydown &&
7789                                      Person::players[i]->crouchkeydown)) {
7790                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
7791                             }
7792                             if (Person::players[i]->isCrouch()) {
7793                                 Person::players[i]->animTarget = sneakanim;
7794                                 if (Person::players[i]->wasCrouch())
7795                                     Person::players[i]->target = 0;
7796                                 Person::players[i]->frameTarget = 0;
7797                             }
7798                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
7799                                 Person::players[i]->velocity -= absflatfacing * 5 * multiplier;
7800                             }
7801                             if (Person::players[i]->animTarget == hanganim) {
7802                                 Person::players[i]->animCurrent = jumpdownanim;
7803                                 Person::players[i]->animTarget = jumpdownanim;
7804                                 Person::players[i]->target = 0;
7805                                 Person::players[i]->frameCurrent = 0;
7806                                 Person::players[i]->frameTarget = 1;
7807                                 Person::players[i]->velocity = 0;
7808                                 Person::players[i]->velocity.y += gravity;
7809                                 Person::players[i]->coords.y -= 1.4;
7810                                 Person::players[i]->grabdelay = 1;
7811                             }
7812                             if ( !Person::players[i]->leftkeydown && !Person::players[i]->rightkeydown)
7813                                 Person::players[i]->targetyaw += 180;
7814                             movekey = 1;
7815                         }
7816                         if ((Person::players[i]->jumpkeydown && !Person::players[i]->jumpclimb) || Person::players[i]->jumpstart) {
7817                             if ((((Person::players[i]->isLanding() && Person::players[i]->frameTarget >= 3) ||
7818                                     Person::players[i]->isRun() ||
7819                                     Person::players[i]->animTarget == walkanim ||
7820                                     Person::players[i]->isCrouch() ||
7821                                     Person::players[i]->animTarget == sneakanim) &&
7822                                     Person::players[i]->jumppower > 1) &&
7823                                     ((Person::players[i]->animTarget != rabbitrunninganim &&
7824                                       Person::players[i]->animTarget != wolfrunninganim) || i != 0)) {
7825                                 Person::players[i]->jumpstart = 0;
7826                                 Person::players[i]->setAnimation(jumpupanim);
7827                                 Person::players[i]->yaw = Person::players[i]->targetyaw;
7828                                 Person::players[i]->transspeed = 20;
7829                                 Person::players[i]->FootLand(0, 1);
7830                                 Person::players[i]->FootLand(1, 1);
7831
7832                                 facing = 0;
7833                                 facing.z = -1;
7834                                 flatfacing = DoRotation(facing, 0, Person::players[i]->targetyaw + 180, 0);
7835
7836                                 if (movekey)
7837                                     Person::players[i]->velocity = flatfacing * Person::players[i]->speed * 45 * Person::players[i]->scale;
7838                                 if (!movekey)
7839                                     Person::players[i]->velocity = 0;
7840
7841                                 //Dodge sweep?
7842                                 target = -2;
7843                                 if (numplayers > 1)
7844                                     for (int j = 0; j < numplayers; j++) {
7845                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim) {
7846                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
7847                                                     (Person::players[j]->victim == Person::players[i]) &&
7848                                                     (Person::players[j]->animTarget == sweepanim)) {
7849                                                 if (target >= 0)
7850                                                     target = -1;
7851                                                 else
7852                                                     target = j;
7853                                             }
7854                                         }
7855                                     }
7856                                 if (target >= 0)
7857                                     Person::players[i]->velocity.y = 1;
7858                                 else
7859                                     if (Person::players[i]->crouchkeydown || Person::players[i]->aitype != playercontrolled) {
7860                                     Person::players[i]->velocity.y = 7;
7861                                     Person::players[i]->crouchtogglekeydown = 1;
7862                                 } else Person::players[i]->velocity.y = 5;
7863
7864                                 if (mousejump && i == 0 && debugmode) {
7865                                     if (!Person::players[i]->isLanding())
7866                                         Person::players[i]->tempdeltav = deltav;
7867                                     if (Person::players[i]->tempdeltav < 0)
7868                                         Person::players[i]->velocity.y -= (float)(Person::players[i]->tempdeltav) / multiplier / 1000;
7869                                 }
7870
7871                                 Person::players[i]->coords.y += .2;
7872                                 Person::players[i]->jumppower -= 1;
7873
7874                                 if (!i)
7875                                     emit_sound_at(whooshsound, Person::players[i]->coords, 128.);
7876
7877                                 emit_sound_at(jumpsound, Person::players[i]->coords, 128.);
7878                             }
7879                             if ((Person::players[i]->isIdle()) && Person::players[i]->jumppower > 1) {
7880                                 Person::players[i]->setAnimation(Person::players[i]->getLanding());
7881                                 Person::players[i]->frameTarget = 2;
7882                                 Person::players[i]->landhard = 0;
7883                                 Person::players[i]->jumpstart = 1;
7884                                 Person::players[i]->tempdeltav = deltav;
7885                             }
7886                             if (Person::players[i]->animTarget == jumpupanim &&
7887                                     (((!floatjump &&
7888                                        !editorenabled) ||
7889                                       !debugmode) ||
7890                                      Person::players[i]->aitype != playercontrolled)) {
7891                                 if (Person::players[i]->jumppower > multiplier * 6) {
7892                                     Person::players[i]->velocity.y += multiplier * 6;
7893                                     Person::players[i]->jumppower -= multiplier * 6;
7894                                 }
7895                                 if (Person::players[i]->jumppower <= multiplier * 6) {
7896                                     Person::players[i]->velocity.y += Person::players[i]->jumppower;
7897                                     Person::players[i]->jumppower = 0;
7898                                 }
7899                             }
7900                             if (((floatjump || editorenabled) && debugmode) && i == 0)
7901                                 Person::players[i]->velocity.y += multiplier * 30;
7902                         }
7903
7904                         if (!movekey) {
7905                             if (Person::players[i]->isRun() || Person::players[i]->animTarget == walkanim)
7906                                 Person::players[i]->setAnimation(Person::players[i]->getStop());
7907                             if (Person::players[i]->animTarget == sneakanim) {
7908                                 Person::players[i]->animTarget = Person::players[i]->getCrouch();
7909                                 if (Person::players[i]->animCurrent == sneakanim)
7910                                     Person::players[i]->target = 0;
7911                                 Person::players[i]->frameTarget = 0;
7912                             }
7913                         }
7914                         if (Person::players[i]->animTarget == walkanim &&
7915                                 (Person::players[i]->aitype == attacktypecutoff ||
7916                                  Person::players[i]->aitype == searchtype ||
7917                                  (Person::players[i]->aitype == passivetype &&
7918                                   Person::players[i]->numwaypoints <= 1)))
7919                             Person::players[i]->setAnimation(Person::players[i]->getStop());
7920                         if (Person::players[i]->isRun() && (Person::players[i]->aitype == passivetype))
7921                             Person::players[i]->setAnimation(Person::players[i]->getStop());
7922                     }
7923                 }
7924                 if (Person::players[i]->animTarget == rollanim)
7925                     Person::players[i]->targetyaw = oldtargetyaw;
7926             }
7927
7928             //Rotation
7929             for (int k = 0; k < numplayers; k++) {
7930                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 180) {
7931                     if (Person::players[k]->yaw > Person::players[k]->targetyaw)
7932                         Person::players[k]->yaw -= 360;
7933                     else
7934                         Person::players[k]->yaw += 360;
7935                 }
7936
7937                 //stop to turn in right direction
7938                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 90 && (Person::players[k]->isRun() || Person::players[k]->animTarget == walkanim))
7939                     Person::players[k]->setAnimation(Person::players[k]->getStop());
7940
7941                 if (Person::players[k]->animTarget == backhandspringanim || Person::players[k]->animTarget == dodgebackanim)
7942                     Person::players[k]->targettilt = 0;
7943
7944                 if (Person::players[k]->animTarget != jumpupanim &&
7945                         Person::players[k]->animTarget != backhandspringanim &&
7946                         Person::players[k]->animTarget != jumpdownanim &&
7947                         !Person::players[k]->isFlip()) {
7948                     Person::players[k]->targettilt = 0;
7949                     if (Person::players[k]->jumppower < 0 && !Person::players[k]->jumpkeydown)
7950                         Person::players[k]->jumppower = 0;
7951                     Person::players[k]->jumppower += multiplier * 7;
7952                     if (Person::players[k]->isCrouch())
7953                         Person::players[k]->jumppower += multiplier * 7;
7954                     if (Person::players[k]->jumppower > 5)
7955                         Person::players[k]->jumppower = 5;
7956                 }
7957
7958                 if (Person::players[k]->isRun())
7959                     Person::players[k]->targettilt = (Person::players[k]->yaw - Person::players[k]->targetyaw) / 4;
7960
7961                 Person::players[k]->tilt = stepTowardf(Person::players[k]->tilt, Person::players[k]->targettilt, multiplier * 150);
7962                 Person::players[k]->grabdelay -= multiplier;
7963             }
7964
7965             //do animations
7966             for (int k = 0; k < numplayers; k++) {
7967                 Person::players[k]->DoAnimations();
7968                 Person::players[k]->whichpatchx = Person::players[k]->coords.x / (terrain.size / subdivision * terrain.scale);
7969                 Person::players[k]->whichpatchz = Person::players[k]->coords.z / (terrain.size / subdivision * terrain.scale);
7970             }
7971
7972             //do stuff
7973             objects.DoStuff();
7974
7975             for (int j = numenvsounds - 1; j >= 0; j--) {
7976                 envsoundlife[j] -= multiplier;
7977                 if (envsoundlife[j] < 0) {
7978                     numenvsounds--;
7979                     envsoundlife[j] = envsoundlife[numenvsounds];
7980                     envsound[j] = envsound[numenvsounds];
7981                 }
7982             }
7983             if (slomo)
7984                 OPENAL_SetFrequency(OPENAL_ALL, slomofreq);
7985             else
7986                 OPENAL_SetFrequency(OPENAL_ALL, 22050);
7987
7988             if (tutoriallevel == 1) {
7989                 XYZ temp;
7990                 XYZ temp2;
7991                 XYZ temp3;
7992                 XYZ oldtemp;
7993                 XYZ oldtemp2;
7994                 temp.x = 1011;
7995                 temp.y = 84;
7996                 temp.z = 491;
7997                 temp2.x = 1025;
7998                 temp2.y = 75;
7999                 temp2.z = 447;
8000                 temp3.x = 1038;
8001                 temp3.y = 76;
8002                 temp3.z = 453;
8003                 oldtemp = temp;
8004                 oldtemp2 = temp2;
8005                 if (tutorialstage >= 51)
8006                     if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
8007                         OPENAL_StopSound(OPENAL_ALL);  // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
8008                         OPENAL_SetFrequency(OPENAL_ALL, 0.001);
8009
8010                         emit_stream_np(stream_menutheme);
8011
8012                         gameon = 0;
8013                         mainmenu = 5;
8014
8015                         fireSound();
8016
8017                         flash();
8018                     }
8019                 if (tutorialstage < 51)
8020                     if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
8021                         emit_sound_at(fireendsound, Person::players[0]->coords);
8022
8023                         Person::players[0]->coords = (oldtemp + oldtemp2) / 2;
8024
8025                         flash();
8026                     }
8027                 if (tutorialstage >= 14 && tutorialstage < 50)
8028                     if (distsq(&temp, &Person::players[1]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[1]->coords) < 4) {
8029                         emit_sound_at(fireendsound, Person::players[1]->coords);
8030
8031                         for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
8032                             if (Random() % 2 == 0) {
8033                                 if (!Person::players[1]->skeleton.free)
8034                                     temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
8035                                 if (Person::players[1]->skeleton.free)
8036                                     temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
8037                                 if (!Person::players[1]->skeleton.free)
8038                                     temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
8039                                 if (Person::players[1]->skeleton.free)
8040                                     temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
8041                                 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
8042                             }
8043                         }
8044
8045                         Person::players[1]->coords = (oldtemp + oldtemp2) / 2;
8046                         for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
8047                             Person::players[1]->skeleton.joints[i].velocity = 0;
8048                             if (Random() % 2 == 0) {
8049                                 if (!Person::players[1]->skeleton.free)
8050                                     temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
8051                                 if (Person::players[1]->skeleton.free)
8052                                     temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
8053                                 if (!Person::players[1]->skeleton.free)
8054                                     temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
8055                                 if (Person::players[1]->skeleton.free)
8056                                     temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
8057                                 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
8058                             }
8059                         }
8060                     }
8061             }
8062
8063
8064             //3d sound
8065             static float gLoc[3];
8066             gLoc[0] = viewer.x;
8067             gLoc[1] = viewer.y;
8068             gLoc[2] = viewer.z;
8069             static float vel[3];
8070             vel[0] = (viewer.x - oldviewer.x) / multiplier;
8071             vel[1] = (viewer.y - oldviewer.y) / multiplier;
8072             vel[2] = (viewer.z - oldviewer.z) / multiplier;
8073
8074             //Set orientation with forward and up vectors
8075             static XYZ upvector;
8076             upvector = 0;
8077             upvector.z = -1;
8078
8079             upvector = DoRotation(upvector, -pitch + 90, 0, 0);
8080             upvector = DoRotation(upvector, 0, 0 - yaw, 0);
8081
8082             facing = 0;
8083             facing.z = -1;
8084
8085             facing = DoRotation(facing, -pitch, 0, 0);
8086             facing = DoRotation(facing, 0, 0 - yaw, 0);
8087
8088
8089             static float ori[6];
8090             ori[0] = -facing.x;
8091             ori[1] = facing.y;
8092             ori[2] = -facing.z;
8093             ori[3] = -upvector.x;
8094             ori[4] = upvector.y;
8095             ori[5] = -upvector.z;
8096
8097             OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
8098             OPENAL_Update();
8099
8100             oldviewer = viewer;
8101         }
8102     }
8103
8104     if (Input::isKeyPressed(SDLK_F1))
8105         Screenshot();
8106 }
8107
8108 void Game::TickOnce()
8109 {
8110     if (mainmenu)
8111         yaw += multiplier * 5;
8112     else if (directing || indialogue == -1) {
8113         yaw += deltah * .7;
8114         if (!invertmouse)
8115             pitch += deltav * .7;
8116         if (invertmouse)
8117             pitch -= deltav * .7;
8118         if (pitch > 90)
8119             pitch = 90;
8120         if (pitch < -70)
8121             pitch = -70;
8122     }
8123 }
8124
8125 void Game::TickOnceAfter()
8126 {
8127     static XYZ colviewer;
8128     static XYZ coltarget;
8129     static XYZ target;
8130     static XYZ col;
8131     static XYZ facing;
8132     static float changedelay;
8133     static bool alldead;
8134     static float unseendelay;
8135     static float cameraspeed;
8136
8137     if (!mainmenu) {
8138         static int oldmusictype = musictype;
8139
8140         if (environment == snowyenvironment)
8141             leveltheme = stream_snowtheme;
8142         if (environment == grassyenvironment)
8143             leveltheme = stream_grasstheme;
8144         if (environment == desertenvironment)
8145             leveltheme = stream_deserttheme;
8146
8147         realthreat = 0;
8148
8149         musictype = leveltheme;
8150         for (int i = 0; i < numplayers; i++) {
8151             if ((Person::players[i]->aitype == attacktypecutoff ||
8152                     Person::players[i]->aitype == getweapontype ||
8153                     Person::players[i]->aitype == gethelptype ||
8154                     Person::players[i]->aitype == searchtype) &&
8155                     !Person::players[i]->dead/*&&Person::players[i]->surprised<=0*/ &&
8156                     (Person::players[i]->animTarget != sneakattackedanim &&
8157                      Person::players[i]->animTarget != knifesneakattackedanim &&
8158                      Person::players[i]->animTarget != swordsneakattackedanim)) {
8159                 musictype = stream_fighttheme;
8160                 realthreat = 1;
8161             }
8162         }
8163         if (Person::players[0]->dead)
8164             musictype = stream_menutheme;
8165
8166
8167         if (musictype == stream_fighttheme)
8168             unseendelay = 1;
8169
8170         if (oldmusictype == stream_fighttheme && musictype != stream_fighttheme) {
8171             unseendelay -= multiplier;
8172             if (unseendelay > 0)
8173                 musictype = stream_fighttheme;
8174         }
8175
8176
8177         if (loading == 2) {
8178             musictype = stream_menutheme;
8179             musicvolume[2] = 512;
8180             musicvolume[0] = 0;
8181             musicvolume[1] = 0;
8182             musicvolume[3] = 0;
8183         }
8184
8185         if (musictoggle)
8186             if (musictype != oldmusictype && musictype == stream_fighttheme)
8187                 emit_sound_np(alarmsound);
8188         musicselected = musictype;
8189
8190         if (musicselected == leveltheme)
8191             musicvolume[0] += multiplier * 450;
8192         else
8193             musicvolume[0] -= multiplier * 450;
8194         if (musicselected == stream_fighttheme)
8195             musicvolume[1] += multiplier * 450;
8196         else
8197             musicvolume[1] -= multiplier * 450;
8198         if (musicselected == stream_menutheme)
8199             musicvolume[2] += multiplier * 450;
8200         else
8201             musicvolume[2] -= multiplier * 450;
8202
8203         for (int i = 0; i < 3; i++) {
8204             if (musicvolume[i] < 0)
8205                 musicvolume[i] = 0;
8206             if (musicvolume[i] > 512)
8207                 musicvolume[i] = 512;
8208         }
8209
8210         if (musicvolume[2] > 128 && !loading && !mainmenu)
8211             musicvolume[2] = 128;
8212
8213         if (musictoggle) {
8214             if (musicvolume[0] > 0 && oldmusicvolume[0] <= 0)
8215                 emit_stream_np(leveltheme, musicvolume[0]);
8216             if (musicvolume[1] > 0 && oldmusicvolume[1] <= 0)
8217                 emit_stream_np(stream_fighttheme, musicvolume[1]);
8218             if (musicvolume[2] > 0 && oldmusicvolume[2] <= 0)
8219                 emit_stream_np(stream_menutheme, musicvolume[2]);
8220             if (musicvolume[0] <= 0 && oldmusicvolume[0] > 0)
8221                 pause_sound(leveltheme);
8222             if (musicvolume[1] <= 0 && oldmusicvolume[1] > 0)
8223                 pause_sound(stream_fighttheme);
8224             if (musicvolume[2] <= 0 && oldmusicvolume[2] > 0)
8225                 pause_sound(stream_menutheme);
8226
8227             if (musicvolume[0] != oldmusicvolume[0])
8228                 OPENAL_SetVolume(channels[leveltheme], musicvolume[0]);
8229             if (musicvolume[1] != oldmusicvolume[1])
8230                 OPENAL_SetVolume(channels[stream_fighttheme], musicvolume[1]);
8231             if (musicvolume[2] != oldmusicvolume[2])
8232                 OPENAL_SetVolume(channels[stream_menutheme], musicvolume[2]);
8233
8234             for (int i = 0; i < 3; i++)
8235                 oldmusicvolume[i] = musicvolume[i];
8236         } else {
8237             pause_sound(leveltheme);
8238             pause_sound(stream_fighttheme);
8239             pause_sound(stream_menutheme);
8240
8241             for (int i = 0; i < 4; i++) {
8242                 oldmusicvolume[i] = 0;
8243                 musicvolume[i] = 0;
8244             }
8245         }
8246
8247         killhotspot = 2;
8248         for (int i = 0; i < numhotspots; i++) {
8249             if (hotspottype[i] > 10 && hotspottype[i] < 20) {
8250                 if (Person::players[hotspottype[i] - 10]->dead == 0)
8251                     killhotspot = 0;
8252                 else if (killhotspot == 2)
8253                     killhotspot = 1;
8254             }
8255         }
8256         if (killhotspot == 2)
8257             killhotspot = 0;
8258
8259
8260         winhotspot = false;
8261         for (int i = 0; i < numhotspots; i++)
8262             if (hotspottype[i] == -1)
8263                 if (distsq(&Person::players[0]->coords, &hotspot[i]) < hotspotsize[i])
8264                     winhotspot = true;
8265
8266         int numalarmed = 0;
8267         for (int i = 1; i < numplayers; i++)
8268             if (!Person::players[i]->dead && Person::players[i]->aitype == attacktypecutoff && Person::players[i]->surprised <= 0)
8269                 numalarmed++;
8270         if (numalarmed > maxalarmed)
8271             maxalarmed = numalarmed;
8272
8273         if (changedelay <= 0 && !loading && !editorenabled && gameon && !tutoriallevel && changedelay != -999 && !won) {
8274             if (Person::players[0]->dead && changedelay <= 0) {
8275                 changedelay = 1;
8276                 targetlevel = whichlevel;
8277             }
8278             alldead = true;
8279             for (int i = 1; i < numplayers; i++) {
8280                 if (!Person::players[i]->dead && Person::players[i]->howactive < typedead1) {
8281                     alldead = false;
8282                     break;
8283                 }
8284             }
8285
8286
8287             if (alldead && !Person::players[0]->dead && maptype == mapkilleveryone) {
8288                 changedelay = 1;
8289                 targetlevel = whichlevel + 1;
8290                 if (targetlevel > numchallengelevels - 1)
8291                     targetlevel = 0;
8292             }
8293             if (winhotspot || windialogue) {
8294                 changedelay = 0.1;
8295                 targetlevel = whichlevel + 1;
8296                 if (targetlevel > numchallengelevels - 1)
8297                     targetlevel = 0;
8298             }
8299
8300
8301             if (killhotspot) {
8302                 changedelay = 1;
8303                 targetlevel = whichlevel + 1;
8304                 if (targetlevel > numchallengelevels - 1)
8305                     targetlevel = 0;
8306             }
8307
8308             if (changedelay > 0 && !Person::players[0]->dead && !won) {
8309                 //high scores, awards, win
8310                 if (campaign) {
8311                     accountactive->winCampaignLevel(whichchoice, bonustotal, leveltime);
8312                     scoreadded = 1;
8313                 } else {
8314                     accountactive->winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
8315                 }
8316                 won = 1;
8317             }
8318         }
8319
8320         if (!winfreeze) {
8321
8322             if (leveltime < 1) {
8323                 loading = 0;
8324                 changedelay = .1;
8325                 alldead = false;
8326                 winhotspot = false;
8327                 killhotspot = 0;
8328             }
8329
8330             if (!editorenabled && gameon && !mainmenu) {
8331                 if (changedelay != -999)
8332                     changedelay -= multiplier / 7;
8333                 if (Person::players[0]->dead)
8334                     targetlevel = whichlevel;
8335                 if (loading == 2 && !campaign) {
8336                     flash();
8337
8338                     fireSound(firestartsound);
8339
8340                     if (!Person::players[0]->dead && targetlevel != whichlevel)
8341                         startbonustotal = bonustotal;
8342                     if (Person::players[0]->dead)
8343                         Loadlevel(whichlevel);
8344                     else
8345                         Loadlevel(targetlevel);
8346
8347                     fireSound();
8348
8349                     loading = 3;
8350                 }
8351                 if (loading == 2 && targetlevel == whichlevel) {
8352                     flash();
8353                     loadtime = 0;
8354
8355                     fireSound(firestartsound);
8356
8357                     Loadlevel(campaignlevels[accountactive->getCampaignChoicesMade()].mapname.c_str());
8358
8359                     fireSound();
8360
8361                     loading = 3;
8362                 }
8363                 if (changedelay <= -999 &&
8364                         whichlevel != -2 &&
8365                         !loading &&
8366                         (Person::players[0]->dead ||
8367                          (alldead && maptype == mapkilleveryone) ||
8368                          (winhotspot) ||
8369                          (killhotspot)))
8370                     loading = 1;
8371                 if ((Person::players[0]->dead ||
8372                         (alldead && maptype == mapkilleveryone) ||
8373                         (winhotspot) ||
8374                         (windialogue) ||
8375                         (killhotspot)) &&
8376                         changedelay <= 0) {
8377                     if (whichlevel != -2 && !loading && !Person::players[0]->dead) {
8378                         winfreeze = true;
8379                         changedelay = -999;
8380                     }
8381                     if (Person::players[0]->dead)
8382                         loading = 1;
8383                 }
8384             }
8385
8386             if (campaign) {
8387                 // campaignchoosenext determines what to do when the level is complete:
8388                 // 0 = load next level
8389                 // 1 = go back to level select screen
8390                 // 2 = stealthload next level
8391                 if (mainmenu == 0 && winfreeze && (campaignlevels[actuallevel].choosenext) == 1) {
8392                     if (campaignlevels[actuallevel].nextlevel.empty())
8393                         endgame = 1;
8394                 } else if (mainmenu == 0 && winfreeze) {
8395                     stealthloading = (campaignlevels[actuallevel].choosenext == 2);
8396
8397                     if (!stealthloading) {
8398                         fireSound(firestartsound);
8399
8400                         flash();
8401                     }
8402
8403                     startbonustotal = 0;
8404
8405                     LoadCampaign();
8406
8407                     loading = 2;
8408                     loadtime = 0;
8409                     targetlevel = 7;
8410                     if (!firstload)
8411                         LoadStuff();
8412                     whichchoice = 0;
8413                     actuallevel = campaignlevels[actuallevel].nextlevel.front();
8414                     visibleloading = 1;
8415                     stillloading = 1;
8416                     Loadlevel(campaignlevels[actuallevel].mapname.c_str());
8417                     campaign = 1;
8418                     mainmenu = 0;
8419                     gameon = 1;
8420                     pause_sound(stream_menutheme);
8421
8422                     stealthloading = 0;
8423                 }
8424             }
8425
8426             if (loading == 3)
8427                 loading = 0;
8428
8429         }
8430
8431         oldmusictype = musictype;
8432     }
8433
8434     facing = 0;
8435     facing.z = -1;
8436
8437     facing = DoRotation(facing, -pitch, 0, 0);
8438     facing = DoRotation(facing, 0, 0 - yaw, 0);
8439     viewerfacing = facing;
8440
8441     if (!cameramode) {
8442         if ((animation[Person::players[0]->animTarget].attack != 3 && animation[Person::players[0]->animCurrent].attack != 3) || Person::players[0]->skeleton.free)
8443             target = Person::players[0]->coords + Person::players[0]->currentoffset * (1 - Person::players[0]->target) * Person::players[0]->scale + Person::players[0]->targetoffset * Person::players[0]->target * Person::players[0]->scale - Person::players[0]->facing * .05;
8444         else
8445             target = Person::players[0]->oldcoords + Person::players[0]->currentoffset * (1 - Person::players[0]->target) * Person::players[0]->scale + Person::players[0]->targetoffset * Person::players[0]->target * Person::players[0]->scale - Person::players[0]->facing * .05;
8446         target.y += .1;
8447         if (Person::players[0]->skeleton.free) {
8448             for (int i = 0; i < Person::players[0]->skeleton.num_joints; i++) {
8449                 if (Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y > target.y)
8450                     target.y = Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y;
8451             }
8452             target.y += .1;
8453         }
8454         if (Person::players[0]->skeleton.free != 2/*&&!autocam*/) {
8455             cameraspeed = 20;
8456             if (findLengthfast(&Person::players[0]->velocity) > 400) {
8457                 cameraspeed = 20 + (findLength(&Person::players[0]->velocity) - 20) * .96;
8458             }
8459             if (Person::players[0]->skeleton.free == 0 && Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim)
8460                 target.y += 1.4;
8461             coltarget = target - cameraloc;
8462             if (findLengthfast(&coltarget) < multiplier * multiplier * 400)
8463                 cameraloc = target;
8464             else {
8465                 Normalise(&coltarget);
8466                 if (Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim && Person::players[0]->animCurrent != climbanim && Person::players[0]->currentoffset.x == 0)
8467                     cameraloc = cameraloc + coltarget * multiplier * cameraspeed;
8468                 else
8469                     cameraloc = cameraloc + coltarget * multiplier * 8;
8470             }
8471             if (editorenabled)
8472                 cameraloc = target;
8473             cameradist += multiplier * 5;
8474             if (cameradist > 2.3)
8475                 cameradist = 2.3;
8476             viewer = cameraloc - facing * cameradist;
8477             colviewer = viewer;
8478             coltarget = cameraloc;
8479             objects.SphereCheckPossible(&colviewer, findDistance(&colviewer, &coltarget));
8480             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
8481                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
8482                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
8483                     colviewer = viewer;
8484                     coltarget = cameraloc;
8485                     if (objects.model[i].LineCheckPossible(&colviewer, &coltarget, &col, &objects.position[i], &objects.yaw[i]) != -1)
8486                         viewer = col;
8487                 }
8488             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
8489                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
8490                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
8491                     colviewer = viewer;
8492                     if (objects.model[i].SphereCheck(&colviewer, .15, &col, &objects.position[i], &objects.yaw[i]) != -1) {
8493                         viewer = colviewer;
8494                     }
8495                 }
8496             cameradist = findDistance(&viewer, &target);
8497             viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .6);
8498             if (cameraloc.y < terrain.getHeight(cameraloc.x, cameraloc.z)) {
8499                 cameraloc.y = terrain.getHeight(cameraloc.x, cameraloc.z);
8500             }
8501         }
8502         /*
8503         //what did autocam do?
8504         if(Person::players[0]->skeleton.free!=2&&autocam){
8505             cameraspeed=20;
8506             if(findLengthfast(&Person::players[0]->velocity)>400){
8507                 cameraspeed=20+(findLength(&Person::players[0]->velocity)-20)*.96;
8508             }
8509             if(Person::players[0]->skeleton.free==0&&Person::players[0]->animTarget!=hanganim&&Person::players[0]->animTarget!=climbanim)target.y+=1.4;
8510             cameradist+=multiplier*5;
8511             if(cameradist>3.3)cameradist=3.3;
8512             coltarget=target-cameraloc;
8513             if(findLengthfast(&coltarget)<multiplier*multiplier*400)cameraloc=target;
8514             else if(findLengthfast(&coltarget)>1)
8515             {
8516                 Normalise(&coltarget);
8517                 if(Person::players[0]->animTarget!=hanganim&&Person::players[0]->animTarget!=climbanim&&Person::players[0]->animCurrent!=climbanim&&Person::players[0]->currentoffset.x==0)cameraloc=cameraloc+coltarget*multiplier*cameraspeed;
8518                 else cameraloc=cameraloc+coltarget*multiplier*8;
8519             }
8520             if(editorenabled)cameraloc=target;
8521             viewer=cameraloc;
8522             colviewer=viewer;
8523             coltarget=cameraloc;
8524             objects.SphereCheckPossible(&colviewer, findDistance(&colviewer,&coltarget));
8525             if(terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
8526                 for(int j=0;j<terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz];j++){
8527                     int i=terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
8528                     colviewer=viewer;
8529                     coltarget=cameraloc;
8530                     if(objects.model[i].LineCheckPossible(&colviewer,&coltarget,&col,&objects.position[i],&objects.yaw[i])!=-1)viewer=col;
8531                 }
8532             if(terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
8533                 for(int j=0;j<terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz];j++){
8534                     int i=terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
8535                     colviewer=viewer;
8536                     if(objects.model[i].SphereCheck(&colviewer,.15,&col,&objects.position[i],&objects.yaw[i])!=-1){
8537                         viewer=colviewer;
8538                     }
8539                 }
8540             cameradist=findDistance(&viewer,&target);
8541             viewer.y=max((double)viewer.y,terrain.getHeight(viewer.x,viewer.z)+.6);
8542             if(cameraloc.y<terrain.getHeight(cameraloc.x,cameraloc.z)){
8543                 cameraloc.y=terrain.getHeight(cameraloc.x,cameraloc.z);
8544             }
8545         }
8546         */
8547         if (camerashake > .8)
8548             camerashake = .8;
8549         //if(woozy>10)woozy=10;
8550         //woozy+=multiplier;
8551         woozy += multiplier;
8552         if (Person::players[0]->dead)
8553             camerashake = 0;
8554         if (Person::players[0]->dead)
8555             woozy = 0;
8556         camerashake -= multiplier * 2;
8557         blackout -= multiplier * 2;
8558         //if(Person::players[0]->isCrouch())woozy-=multiplier*8;
8559         if (camerashake < 0)
8560             camerashake = 0;
8561         if (blackout < 0)
8562             blackout = 0;
8563         //if(woozy<0)woozy=0;
8564         if (camerashake) {
8565             viewer.x += (float)(Random() % 100) * .0005 * camerashake;
8566             viewer.y += (float)(Random() % 100) * .0005 * camerashake;
8567             viewer.z += (float)(Random() % 100) * .0005 * camerashake;
8568         }
8569     }
8570 }
8571