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