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