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