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