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