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