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