]> git.jsancho.org Git - lugaru.git/blob - Source/GameTick.cpp
Rename all C++ headers with .hpp extension
[lugaru.git] / Source / GameTick.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 // Enable full math definitions
22 #define _USE_MATH_DEFINES
23
24 #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 (int 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 (int 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 (int 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                 }
1780
1781                 if (Person::players[closest]->creature == rabbittype) {
1782                     headprop = Person::players[closest]->proportionhead.x / 1.2;
1783                     bodyprop = Person::players[closest]->proportionbody.x / 1.05;
1784                     armprop = Person::players[closest]->proportionarms.x / 1.00;
1785                     legprop = Person::players[closest]->proportionlegs.x / 1.1;
1786                 }
1787
1788
1789                 if (Person::players[closest]->creature == rabbittype) {
1790                     Person::players[closest]->creature = wolftype;
1791                     Person::players[closest]->whichskin = 0;
1792                     Person::players[closest]->skeletonLoad();
1793
1794                     Person::players[closest]->proportionhead = 1.1;
1795                     Person::players[closest]->proportionbody = 1.1;
1796                     Person::players[closest]->proportionarms = 1.1;
1797                     Person::players[closest]->proportionlegs = 1.1;
1798                     Person::players[closest]->proportionlegs.y = 1.1;
1799                     Person::players[closest]->scale = .23 * 5 * Person::players[0]->scale;
1800
1801                     Person::players[closest]->damagetolerance = 300;
1802                 } else {
1803                     Person::players[closest]->creature = rabbittype;
1804                     Person::players[closest]->whichskin = 0;
1805                     Person::players[closest]->skeletonLoad(true);
1806
1807                     Person::players[closest]->proportionhead = 1.2;
1808                     Person::players[closest]->proportionbody = 1.05;
1809                     Person::players[closest]->proportionarms = 1.00;
1810                     Person::players[closest]->proportionlegs = 1.1;
1811                     Person::players[closest]->proportionlegs.y = 1.05;
1812                     Person::players[closest]->scale = .2 * 5 * Person::players[0]->scale;
1813
1814                     Person::players[closest]->damagetolerance = 200;
1815                 }
1816
1817                 if (Person::players[closest]->creature == wolftype) {
1818                     Person::players[closest]->proportionhead = 1.1 * headprop;
1819                     Person::players[closest]->proportionbody = 1.1 * bodyprop;
1820                     Person::players[closest]->proportionarms = 1.1 * armprop;
1821                     Person::players[closest]->proportionlegs = 1.1 * legprop;
1822                 }
1823
1824                 if (Person::players[closest]->creature == rabbittype) {
1825                     Person::players[closest]->proportionhead = 1.2 * headprop;
1826                     Person::players[closest]->proportionbody = 1.05 * bodyprop;
1827                     Person::players[closest]->proportionarms = 1.00 * armprop;
1828                     Person::players[closest]->proportionlegs = 1.1 * legprop;
1829                     Person::players[closest]->proportionlegs.y = 1.05 * legprop;
1830                 }
1831
1832             }
1833         }
1834
1835         /* Decapitate */
1836         if (((Input::isKeyPressed(SDL_SCANCODE_I) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
1837             int closest = -1;
1838             float closestdist = std::numeric_limits<float>::max();
1839
1840             for (unsigned i = 1; i < Person::players.size(); i++) {
1841                 float distance = distsq(&Person::players[i]->coords, &Person::players[0]->coords);
1842                 if (!Person::players[i]->headless)
1843                     if (distance < closestdist) {
1844                         closestdist = distance;
1845                         closest = i;
1846                     }
1847             }
1848
1849             XYZ flatfacing2, flatvelocity2;
1850             XYZ blah;
1851             if (closest != -1 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
1852                 blah = Person::players[closest]->coords;
1853                 XYZ headspurtdirection;
1854                 //int i = Person::players[closest]->skeleton.jointlabels[head];
1855                 Joint& headjoint = Person::players[closest]->joint(head);
1856                 for (int k = 0; k < Person::players[closest]->skeleton.joints.size(); k++) {
1857                     if (!Person::players[closest]->skeleton.free)
1858                         flatvelocity2 = Person::players[closest]->velocity;
1859                     if (Person::players[closest]->skeleton.free)
1860                         flatvelocity2 = headjoint.velocity;
1861                     if (!Person::players[closest]->skeleton.free)
1862                         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;
1863                     if (Person::players[closest]->skeleton.free)
1864                         flatfacing2 = headjoint.position * Person::players[closest]->scale + Person::players[closest]->coords;
1865                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1866                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1867                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1868                     headspurtdirection = headjoint.position - Person::players[closest]->jointPos(neck);
1869                     Normalise(&headspurtdirection);
1870                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, .6, 1);
1871                     flatvelocity2 += headspurtdirection * 8;
1872                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 / 2, 1, 1, 1, .16, 1);
1873                 }
1874                 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1875
1876                 emit_sound_at(splattersound, blah);
1877                 emit_sound_at(breaksound2, blah, 100.);
1878
1879                 if (Person::players[closest]->skeleton.free == 2)
1880                     Person::players[closest]->skeleton.free = 0;
1881                 Person::players[closest]->RagDoll(0);
1882                 Person::players[closest]->dead = 2;
1883                 Person::players[closest]->headless = 1;
1884                 Person::players[closest]->DoBloodBig(3, 165);
1885
1886                 camerashake += .3;
1887             }
1888         }
1889
1890         /* Explode */
1891         if (((Input::isKeyPressed(SDL_SCANCODE_I) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
1892             int closest = findClosestPlayer();
1893             XYZ flatfacing2, flatvelocity2;
1894             XYZ blah;
1895             if (closest >= 0 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
1896                 blah = Person::players[closest]->coords;
1897                 emit_sound_at(splattersound, blah);
1898                 emit_sound_at(breaksound2, blah);
1899
1900                 for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1901                     if (!Person::players[closest]->skeleton.free)
1902                         flatvelocity2 = Person::players[closest]->velocity;
1903                     if (Person::players[closest]->skeleton.free)
1904                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1905                     if (!Person::players[closest]->skeleton.free)
1906                         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;
1907                     if (Person::players[closest]->skeleton.free)
1908                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1909                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1910                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1911                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1912                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1913                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .3, 1);
1914                     Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1915                 }
1916
1917                 for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1918                     if (!Person::players[closest]->skeleton.free)
1919                         flatvelocity2 = Person::players[closest]->velocity;
1920                     if (Person::players[closest]->skeleton.free)
1921                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1922                     if (!Person::players[closest]->skeleton.free)
1923                         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;
1924                     if (Person::players[closest]->skeleton.free)
1925                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1926                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1927                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1928                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1929                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1930                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1931                 }
1932
1933                 for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1934                     if (!Person::players[closest]->skeleton.free)
1935                         flatvelocity2 = Person::players[closest]->velocity;
1936                     if (Person::players[closest]->skeleton.free)
1937                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1938                     if (!Person::players[closest]->skeleton.free)
1939                         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;
1940                     if (Person::players[closest]->skeleton.free)
1941                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1942                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1943                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1944                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1945                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
1946                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
1947                 }
1948
1949                 for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1950                     if (!Person::players[closest]->skeleton.free)
1951                         flatvelocity2 = Person::players[closest]->velocity;
1952                     if (Person::players[closest]->skeleton.free)
1953                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1954                     if (!Person::players[closest]->skeleton.free)
1955                         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;
1956                     if (Person::players[closest]->skeleton.free)
1957                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1958                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1959                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1960                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1961                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
1962                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
1963                 }
1964
1965                 XYZ temppos;
1966                 for (unsigned j = 0; j < Person::players.size(); j++) {
1967                     if (int(j) != closest) {
1968                         if (distsq(&Person::players[j]->coords, &Person::players[closest]->coords) < 25) {
1969                             Person::players[j]->DoDamage((25 - distsq(&Person::players[j]->coords, &Person::players[closest]->coords)) * 60);
1970                             if (Person::players[j]->skeleton.free == 2)
1971                                 Person::players[j]->skeleton.free = 1;
1972                             Person::players[j]->skeleton.longdead = 0;
1973                             Person::players[j]->RagDoll(0);
1974                             for (int i = 0; i < Person::players[j]->skeleton.joints.size(); i++) {
1975                                 temppos = Person::players[j]->skeleton.joints[i].position + Person::players[j]->coords;
1976                                 if (distsq(&temppos, &Person::players[closest]->coords) < 25) {
1977                                     flatvelocity2 = temppos - Person::players[closest]->coords;
1978                                     Normalise(&flatvelocity2);
1979                                     Person::players[j]->skeleton.joints[i].velocity += flatvelocity2 * ((20 - distsq(&temppos, &Person::players[closest]->coords)) * 20);
1980                                 }
1981                             }
1982                         }
1983                     }
1984                 }
1985
1986                 Person::players[closest]->DoDamage(10000);
1987                 Person::players[closest]->RagDoll(0);
1988                 Person::players[closest]->dead = 2;
1989                 Person::players[closest]->coords = 20;
1990                 Person::players[closest]->skeleton.free = 2;
1991
1992                 camerashake += .6;
1993
1994             }
1995         }
1996
1997         /* Enable editor */
1998         if (Input::isKeyPressed(SDL_SCANCODE_M) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1999             editorenabled = !editorenabled;
2000             if (editorenabled) {
2001                 Person::players[0]->damagetolerance = 100000;
2002             } else {
2003                 Person::players[0]->damagetolerance = 200;
2004             }
2005             Person::players[0]->damage = 0; // these lines were in both if and else, but I think they would better fit in the if
2006             Person::players[0]->permanentdamage = 0;
2007             Person::players[0]->superpermanentdamage = 0;
2008             Person::players[0]->bloodloss = 0;
2009             Person::players[0]->deathbleeding = 0;
2010         }
2011     }
2012
2013     //skip level
2014     if (whichlevel != -2 && Input::isKeyPressed(SDL_SCANCODE_K) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !editorenabled) {
2015         targetlevel++;
2016         if (targetlevel > numchallengelevels - 1)
2017             targetlevel = 0;
2018         loading = 1;
2019         leveltime = 5;
2020     }
2021
2022     if (editorenabled) {
2023         if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
2024             int closest = findClosestPlayer();
2025             if (closest >= 0) {
2026                 Person::players.erase(Person::players.begin()+closest);
2027             }
2028         }
2029
2030         if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2031             int closest = findClosestObject();
2032             if (closest >= 0)
2033                 objects.position[closest].y -= 500;
2034         }
2035
2036         if (Input::isKeyPressed(SDL_SCANCODE_M) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
2037             if (objects.numobjects < max_objects - 1) {
2038                 XYZ scenecoords;
2039                 scenecoords.x = Person::players[0]->coords.x;
2040                 scenecoords.z = Person::players[0]->coords.z;
2041                 scenecoords.y = Person::players[0]->coords.y - 3;
2042                 if (editortype == bushtype)
2043                     scenecoords.y = Person::players[0]->coords.y - .5;
2044                 if (editortype == firetype)
2045                     scenecoords.y = Person::players[0]->coords.y - .5;
2046                 //objects.MakeObject(abs(Random()%3),scenecoords,Random()%360);
2047                 float temprotat, temprotat2;
2048                 temprotat = editoryaw;
2049                 temprotat2 = editorpitch;
2050                 if (temprotat < 0 || editortype == bushtype)
2051                     temprotat = Random() % 360;
2052                 if (temprotat2 < 0)
2053                     temprotat2 = Random() % 360;
2054
2055                 objects.MakeObject(editortype, scenecoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
2056                 if (editortype == treetrunktype)
2057                     objects.MakeObject(treeleavestype, scenecoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
2058             }
2059         }
2060
2061         if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2062             Person::players.push_back(shared_ptr<Person>(new Person()));
2063
2064             Person::players.back()->id = Person::players.size()-1;
2065
2066             Person::players.back()->scale = Person::players[0]->scale;
2067             Person::players.back()->creature = rabbittype;
2068             Person::players.back()->howactive = editoractive;
2069
2070             int k = abs(Random() % 2) + 1;
2071             if (k == 0) {
2072                 Person::players.back()->whichskin = 0;
2073             } else if (k == 1) {
2074                 Person::players.back()->whichskin = 1;
2075             } else {
2076                 Person::players.back()->whichskin = 2;
2077             }
2078
2079             Person::players.back()->skeletonLoad(true);
2080
2081             Person::players.back()->skeleton.drawmodelclothes.textureptr.load("Textures/Belt.png", 1);
2082             Person::players.back()->speed = 1 + (float)(Random() % 100) / 1000;
2083
2084             Person::players.back()->targetyaw = Person::players[0]->targetyaw;
2085             Person::players.back()->yaw = Person::players[0]->yaw;
2086
2087             Person::players.back()->coords = Person::players[0]->coords;
2088             Person::players.back()->oldcoords = Person::players.back()->coords;
2089             Person::players.back()->realoldcoords = Person::players.back()->coords;
2090
2091             if (Person::players[0]->creature == wolftype) {
2092                 headprop = Person::players[0]->proportionhead.x / 1.1;
2093                 bodyprop = Person::players[0]->proportionbody.x / 1.1;
2094                 armprop = Person::players[0]->proportionarms.x / 1.1;
2095                 legprop = Person::players[0]->proportionlegs.x / 1.1;
2096             }
2097
2098             if (Person::players[0]->creature == rabbittype) {
2099                 headprop = Person::players[0]->proportionhead.x / 1.2;
2100                 bodyprop = Person::players[0]->proportionbody.x / 1.05;
2101                 armprop = Person::players[0]->proportionarms.x / 1.00;
2102                 legprop = Person::players[0]->proportionlegs.x / 1.1;
2103             }
2104
2105             if (Person::players.back()->creature == wolftype) {
2106                 Person::players.back()->proportionhead = 1.1 * headprop;
2107                 Person::players.back()->proportionbody = 1.1 * bodyprop;
2108                 Person::players.back()->proportionarms = 1.1 * armprop;
2109                 Person::players.back()->proportionlegs = 1.1 * legprop;
2110             }
2111
2112             if (Person::players.back()->creature == rabbittype) {
2113                 Person::players.back()->proportionhead = 1.2 * headprop;
2114                 Person::players.back()->proportionbody = 1.05 * bodyprop;
2115                 Person::players.back()->proportionarms = 1.00 * armprop;
2116                 Person::players.back()->proportionlegs = 1.1 * legprop;
2117                 Person::players.back()->proportionlegs.y = 1.05 * legprop;
2118             }
2119
2120             if (cellophane) {
2121                 Person::players.back()->proportionhead.z = 0;
2122                 Person::players.back()->proportionbody.z = 0;
2123                 Person::players.back()->proportionarms.z = 0;
2124                 Person::players.back()->proportionlegs.z = 0;
2125             }
2126
2127             Person::players.back()->tempanimation = Animation("Tempanim", lowheight, neutral);
2128
2129             Person::players.back()->damagetolerance = 200;
2130
2131             Person::players.back()->protectionhead = Person::players[0]->protectionhead;
2132             Person::players.back()->protectionhigh = Person::players[0]->protectionhigh;
2133             Person::players.back()->protectionlow = Person::players[0]->protectionlow;
2134             Person::players.back()->armorhead = Person::players[0]->armorhead;
2135             Person::players.back()->armorhigh = Person::players[0]->armorhigh;
2136             Person::players.back()->armorlow = Person::players[0]->armorlow;
2137             Person::players.back()->metalhead = Person::players[0]->metalhead;
2138             Person::players.back()->metalhigh = Person::players[0]->metalhigh;
2139             Person::players.back()->metallow = Person::players[0]->metallow;
2140
2141             Person::players.back()->immobile = Person::players[0]->immobile;
2142
2143             Person::players.back()->numclothes = Person::players[0]->numclothes;
2144             for (int i = 0; i < Person::players.back()->numclothes; i++) {
2145                 strcpy(Person::players.back()->clothes[i], Person::players[0]->clothes[i]);
2146                 Person::players.back()->clothestintr[i] = Person::players[0]->clothestintr[i];
2147                 Person::players.back()->clothestintg[i] = Person::players[0]->clothestintg[i];
2148                 Person::players.back()->clothestintb[i] = Person::players[0]->clothestintb[i];
2149             }
2150             Person::players.back()->addClothes();
2151
2152             Person::players.back()->power = Person::players[0]->power;
2153             Person::players.back()->speedmult = Person::players[0]->speedmult;
2154
2155             Person::players.back()->loaded = true;
2156         }
2157
2158         if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
2159             if (Person::players.back()->numwaypoints < 90) {
2160                 Person::players.back()->waypoints[Person::players.back()->numwaypoints] = Person::players[0]->coords;
2161                 Person::players.back()->waypointtype[Person::players.back()->numwaypoints] = editorpathtype;
2162                 Person::players.back()->numwaypoints++;
2163             }
2164         }
2165
2166         if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2167             if (numpathpoints < 30) {
2168                 bool connected, alreadyconnected;
2169                 connected = 0;
2170                 if (numpathpoints > 1)
2171                     for (int i = 0; i < numpathpoints; i++) {
2172                         if (distsq(&pathpoint[i], &Person::players[0]->coords) < .5 && i != pathpointselected && !connected) {
2173                             alreadyconnected = 0;
2174                             for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
2175                                 if (pathpointconnect[pathpointselected][j] == i)
2176                                     alreadyconnected = 1;
2177                             }
2178                             if (!alreadyconnected) {
2179                                 numpathpointconnect[pathpointselected]++;
2180                                 connected = 1;
2181                                 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
2182                             }
2183                         }
2184                     }
2185                 if (!connected) {
2186                     numpathpoints++;
2187                     pathpoint[numpathpoints - 1] = Person::players[0]->coords;
2188                     numpathpointconnect[numpathpoints - 1] = 0;
2189                     if (numpathpoints > 1 && pathpointselected != -1) {
2190                         numpathpointconnect[pathpointselected]++;
2191                         pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
2192                     }
2193                     pathpointselected = numpathpoints - 1;
2194                 }
2195             }
2196         }
2197
2198         if (Input::isKeyPressed(SDL_SCANCODE_PERIOD)) {
2199             pathpointselected++;
2200             if (pathpointselected >= numpathpoints)
2201                 pathpointselected = -1;
2202         }
2203         if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
2204             pathpointselected--;
2205             if (pathpointselected <= -2)
2206                 pathpointselected = numpathpoints - 1;
2207         }
2208         if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
2209             if (pathpointselected != -1) {
2210                 numpathpoints--;
2211                 pathpoint[pathpointselected] = pathpoint[numpathpoints];
2212                 numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
2213                 for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
2214                     pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
2215                 }
2216                 for (int i = 0; i < numpathpoints; i++) {
2217                     for (int j = 0; j < numpathpointconnect[i]; j++) {
2218                         if (pathpointconnect[i][j] == pathpointselected) {
2219                             pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
2220                             numpathpointconnect[i]--;
2221                         }
2222                         if (pathpointconnect[i][j] == numpathpoints) {
2223                             pathpointconnect[i][j] = pathpointselected;
2224                         }
2225                     }
2226                 }
2227                 pathpointselected = numpathpoints - 1;
2228             }
2229         }
2230
2231         if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2232             editortype--;
2233             if (editortype == treeleavestype || editortype == 10)
2234                 editortype--;
2235             if (editortype < 0)
2236                 editortype = firetype;
2237         }
2238
2239         if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2240             editortype++;
2241             if (editortype == treeleavestype || editortype == 10)
2242                 editortype++;
2243             if (editortype > firetype)
2244                 editortype = 0;
2245         }
2246
2247         if (Input::isKeyDown(SDL_SCANCODE_LEFT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2248             editoryaw -= multiplier * 100;
2249             if (editoryaw < -.01)
2250                 editoryaw = -.01;
2251         }
2252
2253         if (Input::isKeyDown(SDL_SCANCODE_RIGHT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2254             editoryaw += multiplier * 100;
2255         }
2256
2257         if (Input::isKeyDown(SDL_SCANCODE_UP) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2258             editorsize += multiplier;
2259         }
2260
2261         if (Input::isKeyDown(SDL_SCANCODE_DOWN) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2262             editorsize -= multiplier;
2263             if (editorsize < .1)
2264                 editorsize = .1;
2265         }
2266
2267
2268         if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2269             mapradius -= multiplier * 10;
2270         }
2271
2272         if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2273             mapradius += multiplier * 10;
2274         }
2275         if (Input::isKeyDown(SDL_SCANCODE_UP) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2276             editorpitch += multiplier * 100;
2277         }
2278
2279         if (Input::isKeyDown(SDL_SCANCODE_DOWN) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
2280             editorpitch -= multiplier * 100;
2281             if (editorpitch < -.01)
2282                 editorpitch = -.01;
2283         }
2284         if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && objects.numobjects && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
2285             int closest = findClosestObject();
2286             if (closest >= 0)
2287                 objects.DeleteObject(closest);
2288         }
2289     }
2290 }
2291
2292 void doJumpReversals()
2293 {
2294     for (unsigned k = 0; k < Person::players.size(); k++)
2295         for (unsigned i = k; i < Person::players.size(); i++) {
2296             if (i == k)
2297                 continue;
2298             if (     Person::players[k]->skeleton.free == 0 &&
2299                      Person::players[i]->skeleton.oldfree == 0 &&
2300                      (Person::players[i]->animTarget == jumpupanim ||
2301                       Person::players[k]->animTarget == jumpupanim) &&
2302                      (Person::players[i]->aitype == playercontrolled ||
2303                       Person::players[k]->aitype == playercontrolled) &&
2304                      ((Person::players[i]->aitype == attacktypecutoff && Person::players[i]->stunned <= 0) ||
2305                       (Person::players[k]->aitype == attacktypecutoff && Person::players[k]->stunned <= 0))) {
2306                 if (     distsq(&Person::players[i]->coords, &Person::players[k]->coords) < 10 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5) &&
2307                          distsqflat(&Person::players[i]->coords, &Person::players[k]->coords) < 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
2308                     //TODO: refactor two huge similar ifs
2309                     if (Person::players[i]->animTarget == jumpupanim &&
2310                             Person::players[k]->animTarget != getupfrombackanim &&
2311                             Person::players[k]->animTarget != getupfromfrontanim &&
2312                             Animation::animations[Person::players[k]->animTarget].height == middleheight &&
2313                             normaldotproduct(Person::players[i]->velocity, Person::players[k]->coords - Person::players[i]->coords) < 0 &&
2314                             ((Person::players[k]->aitype == playercontrolled && Person::players[k]->attackkeydown) ||
2315                              Person::players[k]->aitype != playercontrolled)) {
2316                         Person::players[i]->victim = Person::players[k];
2317                         Person::players[i]->velocity = 0;
2318                         Person::players[i]->animCurrent = jumpreversedanim;
2319                         Person::players[i]->animTarget = jumpreversedanim;
2320                         Person::players[i]->frameCurrent = 0;
2321                         Person::players[i]->frameTarget = 1;
2322                         Person::players[i]->targettilt2 = 0;
2323                         Person::players[k]->victim = Person::players[i];
2324                         Person::players[k]->velocity = 0;
2325                         Person::players[k]->animCurrent = jumpreversalanim;
2326                         Person::players[k]->animTarget = jumpreversalanim;
2327                         Person::players[k]->frameCurrent = 0;
2328                         Person::players[k]->frameTarget = 1;
2329                         Person::players[k]->targettilt2 = 0;
2330                         if (Person::players[i]->coords.y < Person::players[k]->coords.y + 1) {
2331                             Person::players[i]->animCurrent = rabbitkickreversedanim;
2332                             Person::players[i]->animTarget = rabbitkickreversedanim;
2333                             Person::players[i]->frameCurrent = 1;
2334                             Person::players[i]->frameTarget = 2;
2335                             Person::players[k]->animCurrent = rabbitkickreversalanim;
2336                             Person::players[k]->animTarget = rabbitkickreversalanim;
2337                             Person::players[k]->frameCurrent = 1;
2338                             Person::players[k]->frameTarget = 2;
2339                         }
2340                         Person::players[i]->target = 0;
2341                         Person::players[k]->oldcoords = Person::players[k]->coords;
2342                         Person::players[i]->coords = Person::players[k]->coords;
2343                         Person::players[k]->targetyaw = Person::players[i]->targetyaw;
2344                         Person::players[k]->yaw = Person::players[i]->targetyaw;
2345                         if (Person::players[k]->aitype == attacktypecutoff)
2346                             Person::players[k]->stunned = .5;
2347                     }
2348                     if (Person::players[k]->animTarget == jumpupanim &&
2349                             Person::players[i]->animTarget != getupfrombackanim &&
2350                             Person::players[i]->animTarget != getupfromfrontanim &&
2351                             Animation::animations[Person::players[i]->animTarget].height == middleheight &&
2352                             normaldotproduct(Person::players[k]->velocity, Person::players[i]->coords - Person::players[k]->coords) < 0 &&
2353                             ((Person::players[i]->aitype == playercontrolled && Person::players[i]->attackkeydown) ||
2354                              Person::players[i]->aitype != playercontrolled)) {
2355                         Person::players[k]->victim = Person::players[i];
2356                         Person::players[k]->velocity = 0;
2357                         Person::players[k]->animCurrent = jumpreversedanim;
2358                         Person::players[k]->animTarget = jumpreversedanim;
2359                         Person::players[k]->frameCurrent = 0;
2360                         Person::players[k]->frameTarget = 1;
2361                         Person::players[k]->targettilt2 = 0;
2362                         Person::players[i]->victim = Person::players[k];
2363                         Person::players[i]->velocity = 0;
2364                         Person::players[i]->animCurrent = jumpreversalanim;
2365                         Person::players[i]->animTarget = jumpreversalanim;
2366                         Person::players[i]->frameCurrent = 0;
2367                         Person::players[i]->frameTarget = 1;
2368                         Person::players[i]->targettilt2 = 0;
2369                         if (Person::players[k]->coords.y < Person::players[i]->coords.y + 1) {
2370                             Person::players[k]->animTarget = rabbitkickreversedanim;
2371                             Person::players[k]->animCurrent = rabbitkickreversedanim;
2372                             Person::players[i]->animCurrent = rabbitkickreversalanim;
2373                             Person::players[i]->animTarget = rabbitkickreversalanim;
2374                             Person::players[k]->frameCurrent = 1;
2375                             Person::players[k]->frameTarget = 2;
2376                             Person::players[i]->frameCurrent = 1;
2377                             Person::players[i]->frameTarget = 2;
2378                         }
2379                         Person::players[k]->target = 0;
2380                         Person::players[i]->oldcoords = Person::players[i]->coords;
2381                         Person::players[k]->coords = Person::players[i]->coords;
2382                         Person::players[i]->targetyaw = Person::players[k]->targetyaw;
2383                         Person::players[i]->yaw = Person::players[k]->targetyaw;
2384                         if (Person::players[i]->aitype == attacktypecutoff)
2385                             Person::players[i]->stunned = .5;
2386                     }
2387                 }
2388             }
2389         }
2390 }
2391
2392 void doAerialAcrobatics()
2393 {
2394     static XYZ facing, flatfacing;
2395     for (unsigned k = 0; k < Person::players.size(); k++) {
2396         Person::players[k]->turnspeed = 500;
2397
2398         if ((Person::players[k]->isRun() &&
2399                 ((Person::players[k]->targetyaw != rabbitrunninganim &&
2400                   Person::players[k]->targetyaw != wolfrunninganim) ||
2401                  Person::players[k]->frameTarget == 4)) ||
2402                 Person::players[k]->animTarget == removeknifeanim ||
2403                 Person::players[k]->animTarget == crouchremoveknifeanim ||
2404                 Person::players[k]->animTarget == flipanim ||
2405                 Person::players[k]->animTarget == fightsidestep ||
2406                 Person::players[k]->animTarget == walkanim) {
2407             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed);
2408         }
2409
2410
2411         if (Person::players[k]->isStop() ||
2412                 Person::players[k]->isLanding() ||
2413                 Person::players[k]->animTarget == staggerbackhighanim ||
2414                 (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent == sneakanim) ||
2415                 Person::players[k]->animTarget == staggerbackhardanim ||
2416                 Person::players[k]->animTarget == backhandspringanim ||
2417                 Person::players[k]->animTarget == dodgebackanim ||
2418                 Person::players[k]->animTarget == rollanim ||
2419                 (Animation::animations[Person::players[k]->animTarget].attack &&
2420                  Person::players[k]->animTarget != rabbitkickanim &&
2421                  (Person::players[k]->animTarget != crouchstabanim || Person::players[k]->hasvictim) &&
2422                  (Person::players[k]->animTarget != swordgroundstabanim || Person::players[k]->hasvictim))) {
2423             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 2);
2424         }
2425
2426         if (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent != sneakanim) {
2427             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 4);
2428         }
2429
2430         Person::players[k]->DoStuff();
2431         if (Person::players[k]->immobile && k != 0)
2432             Person::players[k]->coords = Person::players[k]->realoldcoords;
2433
2434         //if player's position has changed (?)
2435         if (distsq(&Person::players[k]->coords, &Person::players[k]->realoldcoords) > 0 &&
2436                 !Person::players[k]->skeleton.free &&
2437                 Person::players[k]->animTarget != climbanim &&
2438                 Person::players[k]->animTarget != hanganim) {
2439             XYZ lowpoint, lowpointtarget, lowpoint2, lowpointtarget2, lowpoint3, lowpointtarget3, lowpoint4, lowpointtarget4, lowpoint5, lowpointtarget5, lowpoint6, lowpointtarget6, lowpoint7, lowpointtarget7, colpoint, colpoint2;
2440             int whichhit;
2441             bool tempcollide = 0;
2442
2443             if (Person::players[k]->collide < -.3)
2444                 Person::players[k]->collide = -.3;
2445             if (Person::players[k]->collide > 1)
2446                 Person::players[k]->collide = 1;
2447             Person::players[k]->collide -= multiplier * 30;
2448
2449             //clip to terrain
2450             Person::players[k]->coords.y = max(Person::players[k]->coords.y, terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z));
2451
2452             for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
2453                 int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
2454                 if (objects.type[i] != rocktype ||
2455                         objects.scale[i] > .5 && Person::players[k]->aitype == playercontrolled ||
2456                         objects.position[i].y > Person::players[k]->coords.y) {
2457                     lowpoint = Person::players[k]->coords;
2458                     if (Person::players[k]->animTarget != jumpupanim &&
2459                             Person::players[k]->animTarget != jumpdownanim &&
2460                             !Person::players[k]->isFlip())
2461                         lowpoint.y += 1.25;
2462                     else
2463                         lowpoint.y += 1.3;
2464                     if (     Person::players[k]->coords.y < terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) &&
2465                              Person::players[k]->coords.y > terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) - .1)
2466                         Person::players[k]->coords.y = terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z);
2467                     if (Person::players[k]->SphereCheck(&lowpoint, 1.3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
2468                         flatfacing = lowpoint - Person::players[k]->coords;
2469                         Person::players[k]->coords = lowpoint;
2470                         Person::players[k]->coords.y -= 1.3;
2471                         Person::players[k]->collide = 1;
2472                         tempcollide = 1;
2473                         //wall jumps
2474                         //TODO: refactor four similar blocks
2475                         if (Person::players[k]->aitype == playercontrolled &&
2476                                 (Person::players[k]->animTarget == jumpupanim ||
2477                                  Person::players[k]->animTarget == jumpdownanim ||
2478                                  Person::players[k]->isFlip()) &&
2479                                 !Person::players[k]->jumptogglekeydown &&
2480                                 Person::players[k]->jumpkeydown) {
2481                             lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, -90, 0) * 1.5;
2482                             XYZ tempcoords1 = lowpoint;
2483                             whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
2484                             if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
2485                                 Person::players[k]->setAnimation(walljumpleftanim);
2486                                 emit_sound_at(movewhooshsound, Person::players[k]->coords);
2487                                 if (k == 0)
2488                                     pause_sound(whooshsound);
2489
2490                                 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
2491                                 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
2492                                 if (lowpointtarget.z < 0)
2493                                     Person::players[k]->yaw = 180 - Person::players[k]->yaw;
2494                                 Person::players[k]->targetyaw = Person::players[k]->yaw;
2495                                 Person::players[k]->lowyaw = Person::players[k]->yaw;
2496                                 if (k == 0)
2497                                     numwallflipped++;
2498                             } else {
2499                                 lowpoint = tempcoords1;
2500                                 lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, 90, 0) * 1.5;
2501                                 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
2502                                 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
2503                                     Person::players[k]->setAnimation(walljumprightanim);
2504                                     emit_sound_at(movewhooshsound, Person::players[k]->coords);
2505                                     if (k == 0)
2506                                         pause_sound(whooshsound);
2507
2508                                     lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
2509                                     Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
2510                                     if (lowpointtarget.z < 0)
2511                                         Person::players[k]->yaw = 180 - Person::players[k]->yaw;
2512                                     Person::players[k]->targetyaw = Person::players[k]->yaw;
2513                                     Person::players[k]->lowyaw = Person::players[k]->yaw;
2514                                     if (k == 0)
2515                                         numwallflipped++;
2516                                 } else {
2517                                     lowpoint = tempcoords1;
2518                                     lowpointtarget = lowpoint + Person::players[k]->facing * 2;
2519                                     whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
2520                                     if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
2521                                         Person::players[k]->setAnimation(walljumpbackanim);
2522                                         emit_sound_at(movewhooshsound, Person::players[k]->coords);
2523                                         if (k == 0)
2524                                             pause_sound(whooshsound);
2525
2526                                         lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
2527                                         Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
2528                                         if (lowpointtarget.z < 0)
2529                                             Person::players[k]->yaw = 180 - Person::players[k]->yaw;
2530                                         Person::players[k]->targetyaw = Person::players[k]->yaw;
2531                                         Person::players[k]->lowyaw = Person::players[k]->yaw;
2532                                         if (k == 0)
2533                                             numwallflipped++;
2534                                     } else {
2535                                         lowpoint = tempcoords1;
2536                                         lowpointtarget = lowpoint - Person::players[k]->facing * 2;
2537                                         whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
2538                                         if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
2539                                             Person::players[k]->setAnimation(walljumpfrontanim);
2540                                             emit_sound_at(movewhooshsound, Person::players[k]->coords);
2541                                             if (k == 0)
2542                                                 pause_sound(whooshsound);
2543
2544                                             lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
2545                                             Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
2546                                             if (lowpointtarget.z < 0)
2547                                                 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
2548                                             Person::players[k]->yaw += 180;
2549                                             Person::players[k]->targetyaw = Person::players[k]->yaw;
2550                                             Person::players[k]->lowyaw = Person::players[k]->yaw;
2551                                             if (k == 0)
2552                                                 numwallflipped++;
2553                                         }
2554                                     }
2555                                 }
2556                             }
2557                         }
2558                     }
2559                 } else if (objects.type[i] == rocktype) {
2560                     lowpoint2 = Person::players[k]->coords;
2561                     lowpoint = Person::players[k]->coords;
2562                     lowpoint.y += 2;
2563                     if (objects.model[i].LineCheck(&lowpoint, &lowpoint2, &colpoint, &objects.position[i], &objects.yaw[i]) != -1) {
2564                         Person::players[k]->coords = colpoint;
2565                         Person::players[k]->collide = 1;
2566                         tempcollide = 1;
2567
2568                         if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) {
2569                             //flipped into a rock
2570                             if (Person::players[k]->isFlip() && Person::players[k]->targetFrame().label == 7)
2571                                 Person::players[k]->RagDoll(0);
2572
2573                             if (Person::players[k]->animTarget == jumpupanim) {
2574                                 Person::players[k]->jumppower = -4;
2575                                 Person::players[k]->animTarget = Person::players[k]->getIdle();
2576                             }
2577                             Person::players[k]->target = 0;
2578                             Person::players[k]->frameTarget = 0;
2579                             Person::players[k]->onterrain = 1;
2580
2581                             if (Person::players[k]->id == 0) {
2582                                 pause_sound(whooshsound);
2583                                 OPENAL_SetVolume(channels[whooshsound], 0);
2584                             }
2585
2586                             //landing
2587                             if ((Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) && !Person::players[k]->wasLanding()) {
2588                                 if (Person::players[k]->isFlip())
2589                                     Person::players[k]->jumppower = -4;
2590                                 Person::players[k]->animTarget = Person::players[k]->getLanding();
2591                                 emit_sound_at(landsound, Person::players[k]->coords, 128.);
2592                                 if (k == 0) {
2593                                     addEnvSound(Person::players[k]->coords);
2594                                 }
2595                             }
2596                         }
2597                     }
2598                 }
2599             }
2600
2601             if (tempcollide)
2602                 for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
2603                     int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
2604                     lowpoint = Person::players[k]->coords;
2605                     lowpoint.y += 1.35;
2606                     if (objects.type[i] != rocktype)
2607                         if (Person::players[k]->SphereCheck(&lowpoint, 1.33, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
2608                             if (Person::players[k]->animTarget != jumpupanim &&
2609                                     Person::players[k]->animTarget != jumpdownanim &&
2610                                     Person::players[k]->onterrain)
2611                                 Person::players[k]->avoidcollided = 1;
2612                             Person::players[k]->coords = lowpoint;
2613                             Person::players[k]->coords.y -= 1.35;
2614                             Person::players[k]->collide = 1;
2615
2616                             if ((Person::players[k]->grabdelay <= 0 || Person::players[k]->aitype != playercontrolled) &&
2617                                     (Person::players[k]->animCurrent != climbanim &&
2618                                      Person::players[k]->animCurrent != hanganim &&
2619                                      !Person::players[k]->isWallJump() ||
2620                                      Person::players[k]->animTarget == jumpupanim ||
2621                                      Person::players[k]->animTarget == jumpdownanim)) {
2622                                 lowpoint = Person::players[k]->coords;
2623                                 objects.model[i].SphereCheckPossible(&lowpoint, 1.5, &objects.position[i], &objects.yaw[i]);
2624                                 lowpoint = Person::players[k]->coords;
2625                                 lowpoint.y += .05;
2626                                 facing = 0;
2627                                 facing.z = -1;
2628                                 facing = DoRotation(facing, 0, Person::players[k]->targetyaw + 180, 0);
2629                                 lowpointtarget = lowpoint + facing * 1.4;
2630                                 whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
2631                                 if (whichhit != -1) {
2632                                     lowpoint = Person::players[k]->coords;
2633                                     lowpoint.y += .1;
2634                                     lowpointtarget = lowpoint + facing * 1.4;
2635                                     lowpoint2 = lowpoint;
2636                                     lowpointtarget2 = lowpointtarget;
2637                                     lowpoint3 = lowpoint;
2638                                     lowpointtarget3 = lowpointtarget;
2639                                     lowpoint4 = lowpoint;
2640                                     lowpointtarget4 = lowpointtarget;
2641                                     lowpoint5 = lowpoint;
2642                                     lowpointtarget5 = lowpointtarget;
2643                                     lowpoint6 = lowpoint;
2644                                     lowpointtarget6 = lowpointtarget;
2645                                     lowpoint7 = lowpoint;
2646                                     lowpointtarget7 = lowpoint;
2647                                     lowpoint2.x += .1;
2648                                     lowpointtarget2.x += .1;
2649                                     lowpoint3.z += .1;
2650                                     lowpointtarget3.z += .1;
2651                                     lowpoint4.x -= .1;
2652                                     lowpointtarget4.x -= .1;
2653                                     lowpoint5.z -= .1;
2654                                     lowpointtarget5.z -= .1;
2655                                     lowpoint6.y += 45 / 13;
2656                                     lowpointtarget6.y += 45 / 13;
2657                                     lowpointtarget6 += facing * .6;
2658                                     lowpointtarget7.y += 90 / 13;
2659                                     whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
2660                                     if (objects.friction[i] > .5)
2661                                         if (whichhit != -1) {
2662                                             if (whichhit != -1 && Person::players[k]->animTarget != jumpupanim && Person::players[k]->animTarget != jumpdownanim)
2663                                                 Person::players[k]->collided = 1;
2664                                             if (checkcollide(lowpoint7, lowpointtarget7) == -1)
2665                                                 if (checkcollide(lowpoint6, lowpointtarget6) == -1)
2666                                                     if (     objects.model[i].LineCheckPossible(&lowpoint2, &lowpointtarget2,
2667                                                              &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
2668                                                              objects.model[i].LineCheckPossible(&lowpoint3, &lowpointtarget3,
2669                                                                      &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
2670                                                              objects.model[i].LineCheckPossible(&lowpoint4, &lowpointtarget4,
2671                                                                      &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
2672                                                              objects.model[i].LineCheckPossible(&lowpoint5, &lowpointtarget5,
2673                                                                      &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
2674                                                         for (int j = 0; j < 45; j++) {
2675                                                             lowpoint = Person::players[k]->coords;
2676                                                             lowpoint.y += (float)j / 13;
2677                                                             lowpointtarget = lowpoint + facing * 1.4;
2678                                                             if (objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget,
2679                                                                                                    &colpoint2, &objects.position[i], &objects.yaw[i]) == -1) {
2680                                                                 if (j <= 6 || j <= 25 && Person::players[k]->animTarget == jumpdownanim)
2681                                                                     break;
2682                                                                 if (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim) {
2683                                                                     lowpoint = Person::players[k]->coords;
2684                                                                     lowpoint.y += (float)j / 13;
2685                                                                     lowpointtarget = lowpoint + facing * 1.3;
2686                                                                     flatfacing = Person::players[k]->coords;
2687                                                                     Person::players[k]->coords = colpoint - DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[k], 0) * .01;
2688                                                                     Person::players[k]->coords.y = lowpointtarget.y - .07;
2689                                                                     Person::players[k]->currentoffset = (flatfacing - Person::players[k]->coords) / Person::players[k]->scale;
2690
2691                                                                     if (j > 10 || !Person::players[k]->isRun()) {
2692                                                                         if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->animTarget == jumpupanim) {
2693                                                                             if (k == 0)
2694                                                                                 pause_sound(whooshsound);
2695                                                                         }
2696                                                                         emit_sound_at(jumpsound, Person::players[k]->coords, 128.);
2697
2698                                                                         lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
2699                                                                         Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
2700                                                                         if (lowpointtarget.z < 0)
2701                                                                             Person::players[k]->yaw = 180 - Person::players[k]->yaw;
2702                                                                         Person::players[k]->targetyaw = Person::players[k]->yaw;
2703                                                                         Person::players[k]->lowyaw = Person::players[k]->yaw;
2704
2705                                                                         //Person::players[k]->velocity=lowpointtarget*.03;
2706                                                                         Person::players[k]->velocity = 0;
2707
2708                                                                         //climb ledge (?)
2709                                                                         if (Person::players[k]->animTarget == jumpupanim) {
2710                                                                             Person::players[k]->animTarget = climbanim;
2711                                                                             Person::players[k]->jumppower = 0;
2712                                                                             Person::players[k]->jumpclimb = 1;
2713                                                                         }
2714                                                                         Person::players[k]->transspeed = 6;
2715                                                                         Person::players[k]->target = 0;
2716                                                                         Person::players[k]->frameTarget = 1;
2717                                                                         //hang ledge (?)
2718                                                                         if (j > 25) {
2719                                                                             Person::players[k]->setAnimation(hanganim);
2720                                                                             Person::players[k]->jumppower = 0;
2721                                                                         }
2722                                                                     }
2723                                                                     break;
2724                                                                 }
2725                                                             }
2726                                                         }
2727                                         }
2728                                 }
2729                             }
2730                         }
2731                 }
2732             if (Person::players[k]->collide <= 0) {
2733                 //in the air
2734                 if (!Person::players[k]->onterrain &&
2735                         Person::players[k]->animTarget != jumpupanim &&
2736                         Person::players[k]->animTarget != jumpdownanim &&
2737                         Person::players[k]->animTarget != climbanim &&
2738                         Person::players[k]->animTarget != hanganim &&
2739                         !Person::players[k]->isWallJump() &&
2740                         !Person::players[k]->isFlip()) {
2741                     if (Person::players[k]->animCurrent != climbanim &&
2742                             Person::players[k]->animCurrent != tempanim &&
2743                             Person::players[k]->animTarget != backhandspringanim &&
2744                             (Person::players[k]->animTarget != rollanim ||
2745                              Person::players[k]->frameTarget < 2 ||
2746                              Person::players[k]->frameTarget > 6)) {
2747                         //stagger off ledge (?)
2748                         if (Person::players[k]->animTarget == staggerbackhighanim || Person::players[k]->animTarget == staggerbackhardanim)
2749                             Person::players[k]->RagDoll(0);
2750                         Person::players[k]->setAnimation(jumpdownanim);
2751
2752                         if (!k)
2753                             emit_sound_at(whooshsound, Person::players[k]->coords, 128.);
2754                     }
2755                     //gravity
2756                     Person::players[k]->velocity.y += gravity;
2757                 }
2758             }
2759         }
2760         Person::players[k]->realoldcoords = Person::players[k]->coords;
2761     }
2762 }
2763
2764 void doAttacks()
2765 {
2766     static int randattack;
2767     static bool playerrealattackkeydown = 0;
2768
2769     if (!Input::isKeyDown(attackkey))
2770         oldattackkey = 0;
2771     if (oldattackkey)
2772         Person::players[0]->attackkeydown = 0;
2773     if (oldattackkey)
2774         playerrealattackkeydown = 0;
2775     if (!oldattackkey)
2776         playerrealattackkeydown = Input::isKeyDown(attackkey);
2777     if ((Person::players[0]->parriedrecently <= 0 ||
2778             Person::players[0]->weaponactive == -1) &&
2779             (!oldattackkey ||
2780              (realthreat &&
2781               Person::players[0]->lastattack != swordslashanim &&
2782               Person::players[0]->lastattack != knifeslashstartanim &&
2783               Person::players[0]->lastattack != staffhitanim &&
2784               Person::players[0]->lastattack != staffspinhitanim)))
2785         Person::players[0]->attackkeydown = Input::isKeyDown(attackkey);
2786     if (Input::isKeyDown(attackkey) &&
2787             !oldattackkey &&
2788             !Person::players[0]->backkeydown) {
2789         for (unsigned k = 0; k < Person::players.size(); k++) {
2790             if ((Person::players[k]->animTarget == swordslashanim ||
2791                     Person::players[k]->animTarget == staffhitanim ||
2792                     Person::players[k]->animTarget == staffspinhitanim) &&
2793                     Person::players[0]->animCurrent != dodgebackanim &&
2794                     !Person::players[k]->skeleton.free)
2795                 Person::players[k]->Reverse();
2796         }
2797     }
2798
2799     if (!hostile || Dialog::inDialog())
2800         Person::players[0]->attackkeydown = 0;
2801
2802     for (unsigned k = 0; k < Person::players.size(); k++) {
2803         if (Dialog::inDialog())
2804             Person::players[k]->attackkeydown = 0;
2805         if (Person::players[k]->animTarget != rabbitrunninganim && Person::players[k]->animTarget != wolfrunninganim) {
2806             if (Person::players[k]->aitype != playercontrolled)
2807                 Person::players[k]->victim = Person::players[0];
2808             //attack key pressed
2809             if (Person::players[k]->attackkeydown) {
2810                 //dodge backward
2811                 if (Person::players[k]->backkeydown &&
2812                         Person::players[k]->animTarget != backhandspringanim &&
2813                         (Person::players[k]->isIdle() ||
2814                          Person::players[k]->isStop() ||
2815                          Person::players[k]->isRun() ||
2816                          Person::players[k]->animTarget == walkanim)) {
2817                     if (Person::players[k]->jumppower <= 1) {
2818                         Person::players[k]->jumppower -= 2;
2819                     } else {
2820                         for (unsigned i = 0; i < Person::players.size(); i++) {
2821                             if (i == k)
2822                                 continue;
2823                             if (Person::players[i]->animTarget == swordslashanim ||
2824                                     Person::players[i]->animTarget == knifeslashstartanim ||
2825                                     Person::players[i]->animTarget == staffhitanim ||
2826                                     Person::players[i]->animTarget == staffspinhitanim)
2827                                 if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < 6.5 && !Person::players[i]->skeleton.free) {
2828                                     Person::players[k]->setAnimation(dodgebackanim);
2829                                     Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
2830                                     Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
2831                                 }
2832                         }
2833                         if (Person::players[k]->animTarget != dodgebackanim) {
2834                             if (k == 0)
2835                                 numflipped++;
2836                             Person::players[k]->setAnimation(backhandspringanim);
2837                             Person::players[k]->targetyaw = -yaw + 180;
2838                             if (Person::players[k]->leftkeydown)
2839                                 Person::players[k]->targetyaw -= 45;
2840                             if (Person::players[k]->rightkeydown)
2841                                 Person::players[k]->targetyaw += 45;
2842                             Person::players[k]->yaw = Person::players[k]->targetyaw;
2843                             Person::players[k]->jumppower -= 2;
2844                         }
2845                     }
2846                 }
2847                 //attack
2848                 if (!Animation::animations[Person::players[k]->animTarget].attack &&
2849                         !Person::players[k]->backkeydown &&
2850                         (Person::players[k]->isIdle() ||
2851                          Person::players[k]->isRun() ||
2852                          Person::players[k]->animTarget == walkanim ||
2853                          Person::players[k]->animTarget == sneakanim ||
2854                          Person::players[k]->isCrouch())) {
2855                     const int attackweapon = Person::players[k]->weaponactive == -1 ? 0 : weapons[Person::players[k]->weaponids[Person::players[k]->weaponactive]].getType();
2856                     //normal attacks (?)
2857                     Person::players[k]->hasvictim = 0;
2858                     if (Person::players.size() > 1)
2859                         for (unsigned i = 0; i < Person::players.size(); i++) {
2860                             if (i == k || !(k == 0 || i == 0))
2861                                 continue;
2862                             if (!Person::players[k]->hasvictim)
2863                                 if (Animation::animations[Person::players[k]->animTarget].attack != reversal) {
2864                                     //choose an attack
2865                                     const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
2866                                     if (distance < 4.5 &&
2867                                             !Person::players[i]->skeleton.free &&
2868                                             Person::players[i]->howactive < typedead1 &&
2869                                             Person::players[i]->animTarget != jumpreversedanim &&
2870                                             Person::players[i]->animTarget != rabbitkickreversedanim &&
2871                                             Person::players[i]->animTarget != rabbitkickanim &&
2872                                             Person::players[k]->animTarget != rabbitkickanim &&
2873                                             Person::players[i]->animTarget != getupfrombackanim &&
2874                                             (Person::players[i]->animTarget != staggerbackhighanim &&
2875                                              (Person::players[i]->animTarget != staggerbackhardanim || Person::players[i]->targetFrame().label == 6)) &&
2876                                             Person::players[i]->animTarget != jumpdownanim &&
2877                                             Person::players[i]->animTarget != jumpupanim &&
2878                                             Person::players[i]->animTarget != getupfromfrontanim) {
2879                                         Person::players[k]->victim = Person::players[i];
2880                                         Person::players[k]->hasvictim = 1;
2881                                         if (Person::players[k]->aitype == playercontrolled) { //human player
2882                                             //sweep
2883                                             if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2884                                                     Person::players[k]->crouchkeydown &&
2885                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight)
2886                                                 Person::players[k]->animTarget = sweepanim;
2887                                             //winduppunch
2888                                             else if (distance < 1.5 * sq(Person::players[k]->scale * 5) &&
2889                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2890                                                      !Person::players[k]->forwardkeydown &&
2891                                                      !Person::players[k]->leftkeydown &&
2892                                                      !Person::players[k]->rightkeydown &&
2893                                                      !Person::players[k]->crouchkeydown &&
2894                                                      !attackweapon &&
2895                                                      !reversaltrain)
2896                                                 Person::players[k]->animTarget = winduppunchanim;
2897                                             //upunch
2898                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2899                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2900                                                      !Person::players[k]->forwardkeydown &&
2901                                                      !Person::players[k]->leftkeydown &&
2902                                                      !Person::players[k]->rightkeydown &&
2903                                                      !Person::players[k]->crouchkeydown &&
2904                                                      !attackweapon)
2905                                                 Person::players[k]->animTarget = upunchanim;
2906                                             //knifefollow
2907                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2908                                                      Person::players[i]->staggerdelay > 0 &&
2909                                                      attackweapon == knife &&
2910                                                      Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2)
2911                                                 Person::players[k]->animTarget = knifefollowanim;
2912                                             //knifeslashstart
2913                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2914                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2915                                                      !Person::players[k]->forwardkeydown &&
2916                                                      !Person::players[k]->leftkeydown &&
2917                                                      !Person::players[k]->rightkeydown &&
2918                                                      !Person::players[k]->crouchkeydown &&
2919                                                      attackweapon == knife &&
2920                                                      Person::players[k]->weaponmissdelay <= 0)
2921                                                 Person::players[k]->animTarget = knifeslashstartanim;
2922                                             //swordslash
2923                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2924                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2925                                                      !Person::players[k]->crouchkeydown &&
2926                                                      attackweapon == sword &&
2927                                                      Person::players[k]->weaponmissdelay <= 0)
2928                                                 Person::players[k]->animTarget = swordslashanim;
2929                                             //staffhit
2930                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2931                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2932                                                      !Person::players[k]->crouchkeydown &&
2933                                                      attackweapon == staff &&
2934                                                      Person::players[k]->weaponmissdelay <= 0 &&
2935                                                      !Person::players[k]->leftkeydown &&
2936                                                      !Person::players[k]->rightkeydown &&
2937                                                      !Person::players[k]->forwardkeydown)
2938                                                 Person::players[k]->animTarget = staffhitanim;
2939                                             //staffspinhit
2940                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2941                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2942                                                      !Person::players[k]->crouchkeydown &&
2943                                                      attackweapon == staff &&
2944                                                      Person::players[k]->weaponmissdelay <= 0)
2945                                                 Person::players[k]->animTarget = staffspinhitanim;
2946                                             //spinkick
2947                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2948                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight)
2949                                                 Person::players[k]->animTarget = spinkickanim;
2950                                             //lowkick
2951                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2952                                                      Animation::animations[Person::players[i]->animTarget].height == lowheight &&
2953                                                      Animation::animations[Person::players[k]->animTarget].attack != normalattack)
2954                                                 Person::players[k]->animTarget = lowkickanim;
2955                                         } else { //AI player
2956                                             if (distance < 4.5 * sq(Person::players[k]->scale * 5)) {
2957                                                 randattack = abs(Random() % 5);
2958                                                 if (!attackweapon && distance < 2.5 * sq(Person::players[k]->scale * 5)) {
2959                                                     //sweep
2960                                                     if (randattack == 0 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
2961                                                         Person::players[k]->animTarget = sweepanim;
2962                                                     //upunch
2963                                                     else if (randattack == 1 && Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2964                                                              !attackweapon)
2965                                                         Person::players[k]->animTarget = upunchanim;
2966                                                     //spinkick
2967                                                     else if (randattack == 2 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
2968                                                         Person::players[k]->animTarget = spinkickanim;
2969                                                     //lowkick
2970                                                     else if (Animation::animations[Person::players[i]->animTarget].height == lowheight)
2971                                                         Person::players[k]->animTarget = lowkickanim;
2972                                                 }
2973                                                 if (attackweapon) {
2974                                                     //sweep
2975                                                     if ((tutoriallevel != 1 || !attackweapon) &&
2976                                                             distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2977                                                             randattack == 0 &&
2978                                                             Animation::animations[Person::players[i]->animTarget].height != lowheight)
2979                                                         Person::players[k]->animTarget = sweepanim;
2980                                                     //knifeslashstart
2981                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2982                                                              attackweapon == knife &&
2983                                                              Person::players[k]->weaponmissdelay <= 0)
2984                                                         Person::players[k]->animTarget = knifeslashstartanim;
2985                                                     //swordslash
2986                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
2987                                                                Person::players[0]->hasvictim &&
2988                                                                Person::players[0]->animTarget == swordslashanim) &&
2989                                                              attackweapon == sword &&
2990                                                              Person::players[k]->weaponmissdelay <= 0)
2991                                                         Person::players[k]->animTarget = swordslashanim;
2992                                                     //staffhit
2993                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
2994                                                                Person::players[0]->hasvictim &&
2995                                                                Person::players[0]->animTarget == swordslashanim) &&
2996                                                              attackweapon == staff &&
2997                                                              Person::players[k]->weaponmissdelay <= 0 &&
2998                                                              randattack < 3)
2999                                                         Person::players[k]->animTarget = staffhitanim;
3000                                                     //staffspinhit
3001                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
3002                                                                Person::players[0]->hasvictim &&
3003                                                                Person::players[0]->animTarget == swordslashanim) &&
3004                                                              attackweapon == staff &&
3005                                                              Person::players[k]->weaponmissdelay <= 0 &&
3006                                                              randattack >= 3)
3007                                                         Person::players[k]->animTarget = staffspinhitanim;
3008                                                     //spinkick
3009                                                     else if ((tutoriallevel != 1 || !attackweapon) &&
3010                                                              distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3011                                                              randattack == 1 &&
3012                                                              Animation::animations[Person::players[i]->animTarget].height != lowheight)
3013                                                         Person::players[k]->animTarget = spinkickanim;
3014                                                     //lowkick
3015                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3016                                                              Animation::animations[Person::players[i]->animTarget].height == lowheight &&
3017                                                              Animation::animations[Person::players[k]->animTarget].attack != normalattack)
3018                                                         Person::players[k]->animTarget = lowkickanim;
3019                                                 }
3020                                             }
3021                                         }
3022                                         //upunch becomes wolfslap
3023                                         if (Person::players[k]->animTarget == upunchanim && Person::players[k]->creature == wolftype)
3024                                             Person::players[k]->animTarget = wolfslapanim;
3025                                     }
3026                                     //sneak attacks
3027                                     if ((k == 0) && (tutoriallevel != 1 || tutorialstage == 22) &&
3028                                             Person::players[i]->howactive < typedead1 &&
3029                                             distance < 1.5 * sq(Person::players[k]->scale * 5) &&
3030                                             !Person::players[i]->skeleton.free &&
3031                                             Person::players[i]->animTarget != getupfrombackanim &&
3032                                             Person::players[i]->animTarget != getupfromfrontanim &&
3033                                             (Person::players[i]->surprised > 0 ||
3034                                              Person::players[i]->aitype == passivetype ||
3035                                              attackweapon && Person::players[i]->stunned > 0) &&
3036                                             normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[k]->coords) > 0) {
3037                                         //sneakattack
3038                                         if (!attackweapon) {
3039                                             Person::players[k]->animCurrent = sneakattackanim;
3040                                             Person::players[k]->animTarget = sneakattackanim;
3041                                             Person::players[i]->animCurrent = sneakattackedanim;
3042                                             Person::players[i]->animTarget = sneakattackedanim;
3043                                             Person::players[k]->oldcoords = Person::players[k]->coords;
3044                                             Person::players[k]->coords = Person::players[i]->coords;
3045                                         }
3046                                         //knifesneakattack
3047                                         if (attackweapon == knife) {
3048                                             Person::players[k]->animCurrent = knifesneakattackanim;
3049                                             Person::players[k]->animTarget = knifesneakattackanim;
3050                                             Person::players[i]->animCurrent = knifesneakattackedanim;
3051                                             Person::players[i]->animTarget = knifesneakattackedanim;
3052                                             Person::players[i]->oldcoords = Person::players[i]->coords;
3053                                             Person::players[i]->coords = Person::players[k]->coords;
3054                                         }
3055                                         //swordsneakattack
3056                                         if (attackweapon == sword) {
3057                                             Person::players[k]->animCurrent = swordsneakattackanim;
3058                                             Person::players[k]->animTarget = swordsneakattackanim;
3059                                             Person::players[i]->animCurrent = swordsneakattackedanim;
3060                                             Person::players[i]->animTarget = swordsneakattackedanim;
3061                                             Person::players[i]->oldcoords = Person::players[i]->coords;
3062                                             Person::players[i]->coords = Person::players[k]->coords;
3063                                         }
3064                                         if (attackweapon != staff) {
3065                                             Person::players[k]->victim = Person::players[i];
3066                                             Person::players[k]->hasvictim = 1;
3067                                             Person::players[i]->targettilt2 = 0;
3068                                             Person::players[i]->frameTarget = 1;
3069                                             Person::players[i]->frameCurrent = 0;
3070                                             Person::players[i]->target = 0;
3071                                             Person::players[i]->velocity = 0;
3072                                             Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
3073                                             Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
3074                                             Person::players[k]->frameTarget = Person::players[i]->frameTarget;
3075                                             Person::players[k]->target = Person::players[i]->target;
3076                                             Person::players[k]->velocity = 0;
3077                                             Person::players[k]->targetyaw = Person::players[i]->yaw;
3078                                             Person::players[k]->yaw = Person::players[i]->yaw;
3079                                             Person::players[i]->targetyaw = Person::players[i]->yaw;
3080                                         }
3081                                     }
3082                                     if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
3083                                             Person::players[k]->victim == Person::players[i] &&
3084                                             (!Person::players[i]->skeleton.free)) {
3085                                         oldattackkey = 1;
3086                                         Person::players[k]->frameTarget = 0;
3087                                         Person::players[k]->target = 0;
3088
3089                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
3090                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
3091                                         Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
3092                                         Person::players[k]->lastattack2 = Person::players[k]->lastattack;
3093                                         Person::players[k]->lastattack = Person::players[k]->animTarget;
3094                                     }
3095                                     if (Person::players[k]->animTarget == knifefollowanim &&
3096                                             Person::players[k]->victim == Person::players[i]) {
3097                                         oldattackkey = 1;
3098                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
3099                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
3100                                         Person::players[k]->victim = Person::players[i];
3101                                         Person::players[k]->hasvictim = 1;
3102                                         Person::players[i]->animTarget = knifefollowedanim;
3103                                         Person::players[i]->animCurrent = knifefollowedanim;
3104                                         Person::players[i]->targettilt2 = 0;
3105                                         Person::players[i]->targettilt2 = Person::players[k]->targettilt2;
3106                                         Person::players[i]->frameTarget = 1;
3107                                         Person::players[i]->frameCurrent = 0;
3108                                         Person::players[i]->target = 0;
3109                                         Person::players[i]->velocity = 0;
3110                                         Person::players[k]->animCurrent = knifefollowanim;
3111                                         Person::players[k]->animTarget = knifefollowanim;
3112                                         Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
3113                                         Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
3114                                         Person::players[k]->frameTarget = Person::players[i]->frameTarget;
3115                                         Person::players[k]->target = Person::players[i]->target;
3116                                         Person::players[k]->velocity = 0;
3117                                         Person::players[k]->oldcoords = Person::players[k]->coords;
3118                                         Person::players[i]->coords = Person::players[k]->coords;
3119                                         Person::players[i]->targetyaw = Person::players[k]->targetyaw;
3120                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
3121                                         Person::players[k]->yaw = Person::players[k]->targetyaw;
3122                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
3123                                     }
3124                                 }
3125                         }
3126                     const bool hasstaff = attackweapon == staff;
3127                     if (k == 0 && Person::players.size() > 1)
3128                         for (unsigned i = 0; i < Person::players.size(); i++) {
3129                             if (i == k)
3130                                 continue;
3131                             if ((playerrealattackkeydown || Person::players[i]->dead || !hasstaff) &&
3132                                     Animation::animations[Person::players[k]->animTarget].attack == neutral) {
3133                                 const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
3134                                 if (!Person::players[i]->dead || !realthreat || (!attackweapon && Person::players[k]->crouchkeydown))
3135                                     if (Person::players[i]->skeleton.free)
3136                                         if (distance < 3.5 * sq(Person::players[k]->scale * 5) &&
3137                                                 (Person::players[i]->dead ||
3138                                                  Person::players[i]->skeleton.longdead > 1000 ||
3139                                                  Person::players[k]->isRun() ||
3140                                                  hasstaff ||
3141                                                  (attackweapon &&
3142                                                   (Person::players[i]->skeleton.longdead > 2000 ||
3143                                                    Person::players[i]->damage > Person::players[i]->damagetolerance / 8 ||
3144                                                    Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2) &&
3145                                                   distance < 1.5 * sq(Person::players[k]->scale * 5)))) {
3146                                             Person::players[k]->victim = Person::players[i];
3147                                             Person::players[k]->hasvictim = 1;
3148                                             if (attackweapon && tutoriallevel != 1) {
3149                                                 //crouchstab
3150                                                 if (Person::players[k]->crouchkeydown && attackweapon == knife && distance < 1.5 * sq(Person::players[k]->scale * 5))
3151                                                     Person::players[k]->animTarget = crouchstabanim;
3152                                                 //swordgroundstab
3153                                                 if (Person::players[k]->crouchkeydown && distance < 1.5 * sq(Person::players[k]->scale * 5) && attackweapon == sword)
3154                                                     Person::players[k]->animTarget = swordgroundstabanim;
3155                                                 //staffgroundsmash
3156                                                 if (distance < 3.5 * sq(Person::players[k]->scale * 5) && attackweapon == staff)
3157                                                     Person::players[k]->animTarget = staffgroundsmashanim;
3158                                             }
3159                                             if (distance < 2.5 &&
3160                                                     Person::players[k]->crouchkeydown &&
3161                                                     Person::players[k]->animTarget != crouchstabanim &&
3162                                                     !attackweapon &&
3163                                                     Person::players[i]->dead &&
3164                                                     Person::players[i]->skeleton.free &&
3165                                                     Person::players[i]->skeleton.longdead > 1000) {
3166                                                 Person::players[k]->animTarget = killanim;
3167                                                 //TODO: refactor this out, what does it do?
3168                                                 for (int j = 0; j < terrain.numdecals; j++) {
3169                                                     if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
3170                                                             terrain.decalalivetime[j] < 2)
3171                                                         terrain.DeleteDecal(j);
3172                                                 }
3173                                                 for (int l = 0; l < objects.numobjects; l++) {
3174                                                     if (objects.model[l].type == decalstype)
3175                                                         for (int j = 0; j < objects.model[l].numdecals; j++) {
3176                                                             if ((objects.model[l].decaltype[j] == blooddecal ||
3177                                                                     objects.model[l].decaltype[j] == blooddecalslow) &&
3178                                                                     objects.model[l].decalalivetime[j] < 2)
3179                                                                 objects.model[l].DeleteDecal(j);
3180                                                         }
3181                                                 }
3182                                             }
3183                                             if (!Person::players[i]->dead || musictype != 2)
3184                                                 if (distance < 3.5 &&
3185                                                         (Person::players[k]->isRun() || Person::players[k]->isIdle() && Person::players[k]->attackkeydown) &&
3186                                                         Person::players[k]->staggerdelay <= 0 &&
3187                                                         (Person::players[i]->dead ||
3188                                                          Person::players[i]->skeleton.longdead < 300 &&
3189                                                          Person::players[k]->lastattack != spinkickanim &&
3190                                                          Person::players[i]->skeleton.free) &&
3191                                                         (!Person::players[i]->dead || musictype != stream_fighttheme)) {
3192                                                     Person::players[k]->animTarget = dropkickanim;
3193                                                     for (int j = 0; j < terrain.numdecals; j++) {
3194                                                         if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
3195                                                                 terrain.decalalivetime[j] < 2) {
3196                                                             terrain.DeleteDecal(j);
3197                                                         }
3198                                                     }
3199                                                     for (int l = 0; l < objects.numobjects; l++) {
3200                                                         if (objects.model[l].type == decalstype)
3201                                                             for (int j = 0; j < objects.model[l].numdecals; j++) {
3202                                                                 if ((objects.model[l].decaltype[j] == blooddecal ||
3203                                                                         objects.model[l].decaltype[j] == blooddecalslow) &&
3204                                                                         objects.model[l].decalalivetime[j] < 2) {
3205                                                                     objects.model[l].DeleteDecal(j);
3206                                                                 }
3207                                                             }
3208                                                     }
3209                                                 }
3210                                         }
3211                                 if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
3212                                         Person::players[k]->victim == Person::players[i] &&
3213                                         (!Person::players[i]->skeleton.free ||
3214                                          Person::players[k]->animTarget == killanim ||
3215                                          Person::players[k]->animTarget == crouchstabanim ||
3216                                          Person::players[k]->animTarget == swordgroundstabanim ||
3217                                          Person::players[k]->animTarget == staffgroundsmashanim ||
3218                                          Person::players[k]->animTarget == dropkickanim)) {
3219                                     oldattackkey = 1;
3220                                     Person::players[k]->frameTarget = 0;
3221                                     Person::players[k]->target = 0;
3222
3223                                     XYZ targetpoint = Person::players[i]->coords;
3224                                     if (Person::players[k]->animTarget == crouchstabanim ||
3225                                             Person::players[k]->animTarget == swordgroundstabanim ||
3226                                             Person::players[k]->animTarget == staffgroundsmashanim) {
3227                                         targetpoint += (Person::players[i]->jointPos(abdomen) +
3228                                                         Person::players[i]->jointPos(neck)) / 2 *
3229                                                        Person::players[i]->scale;
3230                                     }
3231                                     Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, targetpoint);
3232                                     Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, targetpoint);
3233
3234                                     if (Person::players[k]->animTarget == crouchstabanim || Person::players[k]->animTarget == swordgroundstabanim) {
3235                                         Person::players[k]->targetyaw += (float)(abs(Random() % 100) - 50) / 4;
3236                                     }
3237
3238                                     if (Person::players[k]->animTarget == staffgroundsmashanim)
3239                                         Person::players[k]->targettilt2 += 10;
3240
3241                                     Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
3242                                     Person::players[k]->lastattack2 = Person::players[k]->lastattack;
3243                                     Person::players[k]->lastattack = Person::players[k]->animTarget;
3244
3245                                     if (Person::players[k]->animTarget == swordgroundstabanim) {
3246                                         Person::players[k]->targetyaw += 30;
3247                                     }
3248                                 }
3249                             }
3250                         }
3251                     if (!Person::players[k]->hasvictim) {
3252                         //find victim
3253                         for (unsigned i = 0; i < Person::players.size(); i++) {
3254                             if (i == k || !(i == 0 || k == 0))
3255                                 continue;
3256                             if (!Person::players[i]->skeleton.free) {
3257                                 if (Person::players[k]->hasvictim) {
3258                                     if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) <
3259                                             distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords))
3260                                         Person::players[k]->victim = Person::players[i];
3261                                 } else {
3262                                     Person::players[k]->victim = Person::players[i];
3263                                     Person::players[k]->hasvictim = 1;
3264                                 }
3265                             }
3266                         }
3267                     }
3268                     if (Person::players[k]->aitype == playercontrolled)
3269                         //rabbit kick
3270                         if (Person::players[k]->attackkeydown &&
3271                                 Person::players[k]->isRun() &&
3272                                 Person::players[k]->wasRun() &&
3273                                 ((Person::players[k]->hasvictim &&
3274                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) < 12 * sq(Person::players[k]->scale * 5) &&
3275                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) > 7 * sq(Person::players[k]->scale * 5) &&
3276                                   !Person::players[k]->victim->skeleton.free &&
3277                                   Person::players[k]->victim->animTarget != getupfrombackanim &&
3278                                   Person::players[k]->victim->animTarget != getupfromfrontanim &&
3279                                   Animation::animations[Person::players[k]->victim->animTarget].height != lowheight &&
3280                                   Person::players[k]->aitype != playercontrolled && //wat???
3281                                   normaldotproduct(Person::players[k]->facing, Person::players[k]->victim->coords - Person::players[k]->coords) > 0 &&
3282                                   Person::players[k]->rabbitkickenabled) ||
3283                                  Person::players[k]->jumpkeydown)) {
3284                             oldattackkey = 1;
3285                             Person::players[k]->setAnimation(rabbitkickanim);
3286                         }
3287                     //update counts
3288                     if (Animation::animations[Person::players[k]->animTarget].attack && k == 0) {
3289                         numattacks++;
3290                         switch (attackweapon) {
3291                         case 0:
3292                             numunarmedattack++;
3293                             break;
3294                         case knife:
3295                             numknifeattack++;
3296                             break;
3297                         case sword:
3298                             numswordattack++;
3299                             break;
3300                         case staff:
3301                             numstaffattack++;
3302                             break;
3303                         }
3304                     }
3305                 }
3306             }
3307         }
3308     }
3309 }
3310
3311 void doPlayerCollisions()
3312 {
3313     static XYZ rotatetarget;
3314     static float collisionradius;
3315     if (Person::players.size() > 1)
3316         for (unsigned k = 0; k < Person::players.size(); k++)
3317             for (unsigned i = k + 1; i < Person::players.size(); i++) {
3318                 //neither player is part of a reversal
3319                 if ((Animation::animations[Person::players[i]->animTarget].attack != reversed &&
3320                         Animation::animations[Person::players[i]->animTarget].attack != reversal &&
3321                         Animation::animations[Person::players[k]->animTarget].attack != reversed &&
3322                         Animation::animations[Person::players[k]->animTarget].attack != reversal) || (i != 0 && k != 0))
3323                     if ((Animation::animations[Person::players[i]->animCurrent].attack != reversed &&
3324                             Animation::animations[Person::players[i]->animCurrent].attack != reversal &&
3325                             Animation::animations[Person::players[k]->animCurrent].attack != reversed &&
3326                             Animation::animations[Person::players[k]->animCurrent].attack != reversal) || (i != 0 && k != 0))
3327                         //neither is sleeping
3328                         if (Person::players[i]->howactive <= typesleeping && Person::players[k]->howactive <= typesleeping)
3329                             if (Person::players[i]->howactive != typesittingwall && Person::players[k]->howactive != typesittingwall)
3330                                 //in same patch, neither is climbing
3331                                 if (Person::players[i]->whichpatchx == Person::players[k]->whichpatchx &&
3332                                         Person::players[i]->whichpatchz == Person::players[k]->whichpatchz &&
3333                                         Person::players[k]->skeleton.oldfree == Person::players[k]->skeleton.free &&
3334                                         Person::players[i]->skeleton.oldfree == Person::players[i]->skeleton.free &&
3335                                         Person::players[i]->animTarget != climbanim &&
3336                                         Person::players[i]->animTarget != hanganim &&
3337                                         Person::players[k]->animTarget != climbanim &&
3338                                         Person::players[k]->animTarget != hanganim)
3339                                     //players are close (bounding box test)
3340                                     if (Person::players[i]->coords.y > Person::players[k]->coords.y - 3)
3341                                         if (Person::players[i]->coords.y < Person::players[k]->coords.y + 3)
3342                                             if (Person::players[i]->coords.x > Person::players[k]->coords.x - 3)
3343                                                 if (Person::players[i]->coords.x < Person::players[k]->coords.x + 3)
3344                                                     if (Person::players[i]->coords.z > Person::players[k]->coords.z - 3)
3345                                                         if (Person::players[i]->coords.z < Person::players[k]->coords.z + 3) {
3346                                                             //spread fire from player to player
3347                                                             if (distsq(&Person::players[i]->coords, &Person::players[k]->coords)
3348                                                                     < 3 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
3349                                                                 if (Person::players[i]->onfire || Person::players[k]->onfire) {
3350                                                                     if (!Person::players[i]->onfire)
3351                                                                         Person::players[i]->CatchFire();
3352                                                                     if (!Person::players[k]->onfire)
3353                                                                         Person::players[k]->CatchFire();
3354                                                                 }
3355                                                             }
3356
3357                                                             XYZ tempcoords1 = Person::players[i]->coords;
3358                                                             XYZ tempcoords2 = Person::players[k]->coords;
3359                                                             if (!Person::players[i]->skeleton.oldfree)
3360                                                                 tempcoords1.y += Person::players[i]->jointPos(abdomen).y * Person::players[i]->scale;
3361                                                             if (!Person::players[k]->skeleton.oldfree)
3362                                                                 tempcoords2.y += Person::players[k]->jointPos(abdomen).y * Person::players[k]->scale;
3363                                                             collisionradius = 1.2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
3364                                                             if (Person::players[0]->hasvictim)
3365                                                                 if (Person::players[0]->animTarget == rabbitkickanim && (k == 0 || i == 0) && !Person::players[0]->victim->skeleton.free)
3366                                                                     collisionradius = 3;
3367                                                             if ((!Person::players[i]->skeleton.oldfree || !Person::players[k]->skeleton.oldfree) &&
3368                                                                     (distsq(&tempcoords1, &tempcoords2) < collisionradius ||
3369                                                                      distsq(&Person::players[i]->coords, &Person::players[k]->coords) < collisionradius)) {
3370                                                                 //jump down on a dead body
3371                                                                 if (k == 0 || i == 0) {
3372                                                                     int l = i ? i : k;
3373                                                                     if (Person::players[0]->animTarget == jumpdownanim &&
3374                                                                             !Person::players[0]->skeleton.oldfree &&
3375                                                                             !Person::players[0]->skeleton.free &&
3376                                                                             Person::players[l]->skeleton.oldfree &&
3377                                                                             Person::players[l]->skeleton.free &&
3378                                                                             Person::players[l]->dead &&
3379                                                                             Person::players[0]->lastcollide <= 0 &&
3380                                                                             fabs(Person::players[l]->coords.y - Person::players[0]->coords.y) < .2 &&
3381                                                                             distsq(&Person::players[0]->coords, &Person::players[l]->coords) < .7 * sq((Person::players[l]->scale + Person::players[0]->scale) * 2.5)) {
3382                                                                         Person::players[0]->coords.y = Person::players[l]->coords.y;
3383                                                                         Person::players[l]->velocity = Person::players[0]->velocity;
3384                                                                         Person::players[l]->skeleton.free = 0;
3385                                                                         Person::players[l]->yaw = 0;
3386                                                                         Person::players[l]->RagDoll(0);
3387                                                                         Person::players[l]->DoDamage(20);
3388                                                                         camerashake += .3;
3389                                                                         Person::players[l]->skeleton.longdead = 0;
3390                                                                         Person::players[0]->lastcollide = 1;
3391                                                                     }
3392                                                                 }
3393
3394                                                                 if (     (Person::players[i]->skeleton.oldfree == 1 && findLengthfast(&Person::players[i]->velocity) > 1) ||
3395                                                                          (Person::players[k]->skeleton.oldfree == 1 && findLengthfast(&Person::players[k]->velocity) > 1) ||
3396                                                                          (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0)) {
3397                                                                     rotatetarget = Person::players[k]->velocity - Person::players[i]->velocity;
3398                                                                     if ((Person::players[i]->animTarget != getupfrombackanim && Person::players[i]->animTarget != getupfromfrontanim ||
3399                                                                             Person::players[i]->skeleton.free) &&
3400                                                                             (Person::players[k]->animTarget != getupfrombackanim && Person::players[k]->animTarget != getupfromfrontanim ||
3401                                                                              Person::players[k]->skeleton.free))
3402                                                                         if ((((k != 0 && findLengthfast(&rotatetarget) > 150 ||
3403                                                                                 k == 0 && findLengthfast(&rotatetarget) > 50 && Person::players[0]->rabbitkickragdoll) &&
3404                                                                                 normaldotproduct(rotatetarget, Person::players[k]->coords - Person::players[i]->coords) > 0) &&
3405                                                                                 (k == 0 ||
3406                                                                                  k != 0 && Person::players[i]->skeleton.oldfree == 1 && Animation::animations[Person::players[k]->animCurrent].attack == neutral ||
3407                                                                                  /*i!=0&&*/Person::players[k]->skeleton.oldfree == 1 && Animation::animations[Person::players[i]->animCurrent].attack == neutral)) ||
3408                                                                                 (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) &&
3409                                                                                 (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) &&
3410                                                                                 k == 0 && !Person::players[i]->skeleton.oldfree && !Person::players[k]->skeleton.oldfree) {
3411                                                                             //If hit by body
3412                                                                             if (     (i != 0 || Person::players[i]->skeleton.free) &&
3413                                                                                      (k != 0 || Person::players[k]->skeleton.free) ||
3414                                                                                      (Animation::animations[Person::players[i]->animTarget].height == highheight &&
3415                                                                                       Animation::animations[Person::players[k]->animTarget].height == highheight)) {
3416                                                                                 if (tutoriallevel != 1) {
3417                                                                                     emit_sound_at(heavyimpactsound, Person::players[i]->coords);
3418                                                                                 }
3419
3420                                                                                 Person::players[i]->RagDoll(0);
3421                                                                                 if (Person::players[i]->damage > Person::players[i]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[i]->dead) {
3422                                                                                     award_bonus(0, aimbonus);
3423                                                                                 }
3424                                                                                 Person::players[i]->DoDamage(findLengthfast(&rotatetarget) / 4);
3425                                                                                 Person::players[k]->RagDoll(0);
3426                                                                                 if (Person::players[k]->damage > Person::players[k]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[k]->dead) {
3427                                                                                     award_bonus(0, aimbonus); // Huh, again?
3428                                                                                 }
3429                                                                                 Person::players[k]->DoDamage(findLengthfast(&rotatetarget) / 4);
3430
3431                                                                                 for (int j = 0; j < Person::players[i]->skeleton.joints.size(); j++) {
3432                                                                                     Person::players[i]->skeleton.joints[j].velocity = Person::players[i]->skeleton.joints[j].velocity / 5 + Person::players[k]->velocity;
3433                                                                                 }
3434                                                                                 for (int j = 0; j < Person::players[k]->skeleton.joints.size(); j++) {
3435                                                                                     Person::players[k]->skeleton.joints[j].velocity = Person::players[k]->skeleton.joints[j].velocity / 5 + Person::players[i]->velocity;
3436                                                                                 }
3437
3438                                                                             }
3439                                                                         }
3440                                                                     if (     (Animation::animations[Person::players[i]->animTarget].attack == neutral ||
3441                                                                               Animation::animations[Person::players[i]->animTarget].attack == normalattack) &&
3442                                                                              (Animation::animations[Person::players[k]->animTarget].attack == neutral ||
3443                                                                               Animation::animations[Person::players[k]->animTarget].attack == normalattack)) {
3444                                                                         //If bumped
3445                                                                         if (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0) {
3446                                                                             if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < .5 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
3447                                                                                 rotatetarget = Person::players[k]->coords - Person::players[i]->coords;
3448                                                                                 Normalise(&rotatetarget);
3449                                                                                 Person::players[k]->coords = (Person::players[k]->coords + Person::players[i]->coords) / 2;
3450                                                                                 Person::players[i]->coords = Person::players[k]->coords - rotatetarget * fast_sqrt(.6) / 2
3451                                                                                                    * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
3452                                                                                 Person::players[k]->coords += rotatetarget * fast_sqrt(.6) / 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
3453                                                                                 if (Person::players[k]->howactive == typeactive || hostile)
3454                                                                                     if (Person::players[k]->isIdle()) {
3455                                                                                         if (Person::players[k]->howactive < typesleeping)
3456                                                                                             Person::players[k]->setAnimation(Person::players[k]->getStop());
3457                                                                                         else if (Person::players[k]->howactive == typesleeping)
3458                                                                                             Person::players[k]->setAnimation(getupfromfrontanim);
3459                                                                                         if (!editorenabled)
3460                                                                                             Person::players[k]->howactive = typeactive;
3461                                                                                     }
3462                                                                                 if (Person::players[i]->howactive == typeactive || hostile)
3463                                                                                     if (Person::players[i]->isIdle()) {
3464                                                                                         if (Person::players[i]->howactive < typesleeping)
3465                                                                                             Person::players[i]->setAnimation(Person::players[k]->getStop());
3466                                                                                         else
3467                                                                                             Person::players[i]->setAnimation(getupfromfrontanim);
3468                                                                                         if (!editorenabled)
3469                                                                                             Person::players[i]->howactive = typeactive;
3470                                                                                     }
3471                                                                             }
3472                                                                             //jump down on player
3473                                                                             if (hostile) {
3474                                                                                 if (k == 0 && i != 0 && Person::players[k]->animTarget == jumpdownanim &&
3475                                                                                         !Person::players[i]->isCrouch() &&
3476                                                                                         Person::players[i]->animTarget != rollanim &&
3477                                                                                         !Person::players[k]->skeleton.oldfree && !
3478                                                                                         Person::players[k]->skeleton.free &&
3479                                                                                         Person::players[k]->lastcollide <= 0 &&
3480                                                                                         Person::players[k]->velocity.y < -10) {
3481                                                                                     Person::players[i]->velocity = Person::players[k]->velocity;
3482                                                                                     Person::players[k]->velocity = Person::players[k]->velocity * -.5;
3483                                                                                     Person::players[k]->velocity.y = Person::players[i]->velocity.y;
3484                                                                                     Person::players[i]->DoDamage(20);
3485                                                                                     Person::players[i]->RagDoll(0);
3486                                                                                     Person::players[k]->lastcollide = 1;
3487                                                                                     award_bonus(k, AboveBonus);
3488                                                                                 }
3489                                                                                 if (i == 0 && k != 0 && Person::players[i]->animTarget == jumpdownanim &&
3490                                                                                         !Person::players[k]->isCrouch() &&
3491                                                                                         Person::players[k]->animTarget != rollanim &&
3492                                                                                         !Person::players[i]->skeleton.oldfree &&
3493                                                                                         !Person::players[i]->skeleton.free &&
3494                                                                                         Person::players[i]->lastcollide <= 0 &&
3495                                                                                         Person::players[i]->velocity.y < -10) {
3496                                                                                     Person::players[k]->velocity = Person::players[i]->velocity;
3497                                                                                     Person::players[i]->velocity = Person::players[i]->velocity * -.3;
3498                                                                                     Person::players[i]->velocity.y = Person::players[k]->velocity.y;
3499                                                                                     Person::players[k]->DoDamage(20);
3500                                                                                     Person::players[k]->RagDoll(0);
3501                                                                                     Person::players[i]->lastcollide = 1;
3502                                                                                     award_bonus(i, AboveBonus);
3503                                                                                 }
3504                                                                             }
3505                                                                         }
3506                                                                     }
3507                                                                 }
3508                                                                 Person::players[i]->CheckKick();
3509                                                                 Person::players[k]->CheckKick();
3510                                                             }
3511                                                         }
3512             }
3513 }
3514
3515 void doAI(unsigned i)
3516 {
3517     static bool connected;
3518     if (Person::players[i]->aitype != playercontrolled && !Dialog::inDialog()) {
3519         Person::players[i]->jumpclimb = 0;
3520         //disable movement in editor
3521         if (editorenabled)
3522             Person::players[i]->stunned = 1;
3523
3524         Person::players[i]->pause = 0;
3525         if (distsqflat(&Person::players[0]->coords, &Person::players[i]->coords) < 30 &&
3526                 Person::players[0]->coords.y > Person::players[i]->coords.y + 2 &&
3527                 !Person::players[0]->onterrain)
3528             Person::players[i]->pause = 1;
3529
3530         //pathfinding
3531         if (Person::players[i]->aitype == pathfindtype) {
3532             if (Person::players[i]->finalpathfindpoint == -1) {
3533                 float closestdistance;
3534                 float tempdist;
3535                 int closest;
3536                 XYZ colpoint;
3537                 closest = -1;
3538                 closestdistance = -1;
3539                 for (int j = 0; j < numpathpoints; j++)
3540                     if (closest == -1 || distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]) < closestdistance) {
3541                         closestdistance = distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]);
3542                         closest = j;
3543                         Person::players[i]->finaltarget = pathpoint[j];
3544                     }
3545                 Person::players[i]->finalpathfindpoint = closest;
3546                 for (int j = 0; j < numpathpoints; j++)
3547                     for (int k = 0; k < numpathpointconnect[j]; k++) {
3548                         DistancePointLine(&Person::players[i]->finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
3549                         if (sq(tempdist) < closestdistance)
3550                             if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
3551                                     findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
3552                                 closestdistance = sq(tempdist);
3553                                 closest = j;
3554                                 Person::players[i]->finaltarget = colpoint;
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 (int 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 (int i = 0; i < Hotspot::hotspots.size(); i++)
4697                         hotspotvisual[i] -= multiplier / 320;
4698
4699                 for (int i = 0; i < Hotspot::hotspots.size(); i++) {
4700                     while (hotspotvisual[i] < 0) {
4701                         hotspotsprite = 0;
4702                         hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * Hotspot::hotspots[i].size;
4703                         hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
4704                         hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
4705                         hotspotsprite += Hotspot::hotspots[i].position;
4706                         Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
4707                         hotspotvisual[i] += 0.1 / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size;
4708                     }
4709                 }
4710
4711                 for (int i = 0; i < Hotspot::hotspots.size(); i++) {
4712                     if (Hotspot::hotspots[i].type <= 10 && Hotspot::hotspots[i].type > 0) {
4713                         Hotspot::hotspots[i].position = Person::players[Hotspot::hotspots[i].type]->coords;
4714                     }
4715                 }
4716             }
4717
4718             //Tutorial
4719             if (tutoriallevel) {
4720                 doTutorial();
4721             }
4722
4723             //bonuses
4724             if (tutoriallevel != 1) {
4725                 if (bonustime == 0 &&
4726                         bonus != solidhit &&
4727                         bonus != spinecrusher &&
4728                         bonus != tracheotomy &&
4729                         bonus != backstab &&
4730                         bonusvalue > 10) {
4731                     emit_sound_np(consolesuccesssound);
4732                 }
4733             } else if (bonustime == 0) {
4734                 emit_sound_np(fireendsound);
4735             }
4736             if (bonustime == 0) {
4737                 if (bonus != solidhit &&
4738                         bonus != twoxcombo &&
4739                         bonus != threexcombo &&
4740                         bonus != fourxcombo &&
4741                         bonus != megacombo)
4742                     bonusnum[bonus]++;
4743                 else
4744                     bonusnum[bonus] += 0.15;
4745                 if (tutoriallevel)
4746                     bonusvalue = 0;
4747                 bonusvalue /= bonusnum[bonus];
4748                 bonustotal += bonusvalue;
4749             }
4750             bonustime += multiplier;
4751
4752             //snow effects
4753             if (environment == snowyenvironment) {
4754                 precipdelay -= multiplier;
4755                 while (precipdelay < 0) {
4756                     precipdelay += .04;
4757                     if (!detail)
4758                         precipdelay += .04;
4759                     XYZ footvel, footpoint;
4760
4761                     footvel = 0;
4762                     footpoint = viewer + viewerfacing * 6;
4763                     footpoint.y += ((float)abs(Random() % 1200)) / 100 - 6;
4764                     footpoint.x += ((float)abs(Random() % 1200)) / 100 - 6;
4765                     footpoint.z += ((float)abs(Random() % 1200)) / 100 - 6;
4766                     Sprite::MakeSprite(snowsprite, footpoint, footvel, 1, 1, 1, .1, 1);
4767                 }
4768             }
4769
4770
4771             doAerialAcrobatics();
4772
4773
4774             static XYZ oldviewer;
4775
4776             //control keys
4777             if (!Dialog::inDialog()) {
4778                 Person::players[0]->forwardkeydown = Input::isKeyDown(forwardkey);
4779                 Person::players[0]->leftkeydown = Input::isKeyDown(leftkey);
4780                 Person::players[0]->backkeydown = Input::isKeyDown(backkey);
4781                 Person::players[0]->rightkeydown = Input::isKeyDown(rightkey);
4782                 Person::players[0]->jumpkeydown = Input::isKeyDown(jumpkey);
4783                 Person::players[0]->crouchkeydown = Input::isKeyDown(crouchkey);
4784                 Person::players[0]->drawkeydown = Input::isKeyDown(drawkey);
4785                 Person::players[0]->throwkeydown = Input::isKeyDown(throwkey);
4786             } else {
4787                 Person::players[0]->forwardkeydown = 0;
4788                 Person::players[0]->leftkeydown = 0;
4789                 Person::players[0]->backkeydown = 0;
4790                 Person::players[0]->rightkeydown = 0;
4791                 Person::players[0]->jumpkeydown = 0;
4792                 Person::players[0]->crouchkeydown = 0;
4793                 Person::players[0]->drawkeydown = 0;
4794                 Person::players[0]->throwkeydown = 0;
4795             }
4796
4797             if (!Person::players[0]->jumpkeydown)
4798                 Person::players[0]->jumpclimb = 0;
4799
4800
4801             if (Dialog::inDialog()) {
4802                 cameramode = 1;
4803                 if (Dialog::directing) {
4804                     facing = 0;
4805                     facing.z = -1;
4806
4807                     facing = DoRotation(facing, -pitch, 0, 0);
4808                     facing = DoRotation(facing, 0, 0 - yaw, 0);
4809
4810                     flatfacing = 0;
4811                     flatfacing.z = -1;
4812
4813                     flatfacing = DoRotation(flatfacing, 0, -yaw, 0);
4814
4815                     if (Input::isKeyDown(forwardkey))
4816                         viewer += facing * multiplier * 4;
4817                     if (Input::isKeyDown(backkey))
4818                         viewer -= facing * multiplier * 4;
4819                     if (Input::isKeyDown(leftkey))
4820                         viewer += DoRotation(flatfacing * multiplier, 0, 90, 0) * 4;
4821                     if (Input::isKeyDown(rightkey))
4822                         viewer += DoRotation(flatfacing * multiplier, 0, -90, 0) * 4;
4823                     if (Input::isKeyDown(jumpkey))
4824                         viewer.y += multiplier * 4;
4825                     if (Input::isKeyDown(crouchkey))
4826                         viewer.y -= multiplier * 4;
4827                     if (     Input::isKeyPressed(SDL_SCANCODE_1) ||
4828                              Input::isKeyPressed(SDL_SCANCODE_2) ||
4829                              Input::isKeyPressed(SDL_SCANCODE_3) ||
4830                              Input::isKeyPressed(SDL_SCANCODE_4) ||
4831                              Input::isKeyPressed(SDL_SCANCODE_5) ||
4832                              Input::isKeyPressed(SDL_SCANCODE_6) ||
4833                              Input::isKeyPressed(SDL_SCANCODE_7) ||
4834                              Input::isKeyPressed(SDL_SCANCODE_8) ||
4835                              Input::isKeyPressed(SDL_SCANCODE_9) ||
4836                              Input::isKeyPressed(SDL_SCANCODE_0) ||
4837                              Input::isKeyPressed(SDL_SCANCODE_MINUS)) {
4838                         int whichend;
4839                         if (Input::isKeyPressed(SDL_SCANCODE_1)) whichend = 1;
4840                         if (Input::isKeyPressed(SDL_SCANCODE_2)) whichend = 2;
4841                         if (Input::isKeyPressed(SDL_SCANCODE_3)) whichend = 3;
4842                         if (Input::isKeyPressed(SDL_SCANCODE_4)) whichend = 4;
4843                         if (Input::isKeyPressed(SDL_SCANCODE_5)) whichend = 5;
4844                         if (Input::isKeyPressed(SDL_SCANCODE_6)) whichend = 6;
4845                         if (Input::isKeyPressed(SDL_SCANCODE_7)) whichend = 7;
4846                         if (Input::isKeyPressed(SDL_SCANCODE_8)) whichend = 8;
4847                         if (Input::isKeyPressed(SDL_SCANCODE_9)) whichend = 9;
4848                         if (Input::isKeyPressed(SDL_SCANCODE_0)) whichend = 0;
4849                         if (Input::isKeyPressed(SDL_SCANCODE_MINUS))
4850                             whichend = -1;
4851                         if (whichend != -1) {
4852                             Dialog::currentScene().participantfocus = whichend;
4853                             Dialog::currentDialog().participantlocation[whichend] = Person::players[whichend]->coords;
4854                             Dialog::currentDialog().participantyaw[whichend] = Person::players[whichend]->yaw;
4855                         }
4856                         if (whichend == -1) {
4857                             Dialog::currentScene().participantfocus = -1;
4858                         }
4859                         /* FIXME: potentially accessing -1 in Person::players! */
4860                         if (Person::players[Dialog::currentScene().participantfocus]->dead) {
4861                             Dialog::indialogue = -1;
4862                             Dialog::directing = false;
4863                             cameramode = 0;
4864                         }
4865                         Dialog::currentScene().camera = viewer;
4866                         Dialog::currentScene().camerayaw = yaw;
4867                         Dialog::currentScene().camerapitch = pitch;
4868                         Dialog::indialogue++;
4869                         if (Dialog::indialogue < Dialog::currentDialog().scenes.size()) {
4870                             if (Dialog::currentScene().sound != 0) {
4871                                 playdialoguescenesound();
4872                             }
4873                         }
4874
4875                         for (unsigned j = 0; j < Person::players.size(); j++) {
4876                             Dialog::currentScene().participantfacing[j] = Dialog::currentDialog().scenes[Dialog::indialogue - 1].participantfacing[j];
4877                         }
4878                     }
4879                     //TODO: should these be KeyDown or KeyPressed?
4880                     if (     Input::isKeyDown(SDL_SCANCODE_KP_1) ||
4881                              Input::isKeyDown(SDL_SCANCODE_KP_2) ||
4882                              Input::isKeyDown(SDL_SCANCODE_KP_3) ||
4883                              Input::isKeyDown(SDL_SCANCODE_KP_4) ||
4884                              Input::isKeyDown(SDL_SCANCODE_KP_5) ||
4885                              Input::isKeyDown(SDL_SCANCODE_KP_6) ||
4886                              Input::isKeyDown(SDL_SCANCODE_KP_7) ||
4887                              Input::isKeyDown(SDL_SCANCODE_KP_8) ||
4888                              Input::isKeyDown(SDL_SCANCODE_KP_9) ||
4889                              Input::isKeyDown(SDL_SCANCODE_KP_0)) {
4890                         int whichend;
4891                         if (Input::isKeyDown(SDL_SCANCODE_KP_1)) whichend = 1;
4892                         if (Input::isKeyDown(SDL_SCANCODE_KP_2)) whichend = 2;
4893                         if (Input::isKeyDown(SDL_SCANCODE_KP_3)) whichend = 3;
4894                         if (Input::isKeyDown(SDL_SCANCODE_KP_4)) whichend = 4;
4895                         if (Input::isKeyDown(SDL_SCANCODE_KP_5)) whichend = 5;
4896                         if (Input::isKeyDown(SDL_SCANCODE_KP_6)) whichend = 6;
4897                         if (Input::isKeyDown(SDL_SCANCODE_KP_7)) whichend = 7;
4898                         if (Input::isKeyDown(SDL_SCANCODE_KP_8)) whichend = 8;
4899                         if (Input::isKeyDown(SDL_SCANCODE_KP_9)) whichend = 9;
4900                         if (Input::isKeyDown(SDL_SCANCODE_KP_0)) whichend = 0;
4901                         Dialog::currentScene().participantfacing[whichend] = facing;
4902                     }
4903                     if (Dialog::indialogue >= Dialog::currentDialog().scenes.size()) {
4904                         Dialog::indialogue = -1;
4905                         Dialog::directing = false;
4906                         cameramode = 0;
4907                     }
4908                 }
4909                 if (!Dialog::directing) {
4910                     pause_sound(whooshsound);
4911                     viewer = Dialog::currentScene().camera;
4912                     viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .1);
4913                     yaw = Dialog::currentScene().camerayaw;
4914                     pitch = Dialog::currentScene().camerapitch;
4915                     if (Dialog::dialoguetime > 0.5) {
4916                         if (Input::isKeyPressed(attackkey)) {
4917                             Dialog::indialogue++;
4918                             if (Dialog::indialogue < Dialog::currentDialog().scenes.size()) {
4919                                 if (Dialog::currentScene().sound != 0) {
4920                                     playdialoguescenesound();
4921                                     if (Dialog::currentScene().sound == -5) {
4922                                         Hotspot::hotspots.emplace_back(Person::players[0]->coords, -1, 10);
4923                                     }
4924                                     if (Dialog::currentScene().sound == -6) {
4925                                         hostile = 1;
4926                                     }
4927
4928                                     if (Person::players[Dialog::currentScene().participantfocus]->dead) {
4929                                         Dialog::indialogue = -1;
4930                                         Dialog::directing = false;
4931                                         cameramode = 0;
4932                                     }
4933                                 }
4934                             }
4935                         }
4936                     }
4937                     if (Dialog::indialogue >= Dialog::currentDialog().scenes.size()) {
4938                         Dialog::indialogue = -1;
4939                         Dialog::directing = false;
4940                         cameramode = 0;
4941                         if (Dialog::currentDialog().type > 19 && Dialog::currentDialog().type < 30) {
4942                             hostile = 1;
4943                         }
4944                         if (Dialog::currentDialog().type > 29 && Dialog::currentDialog().type < 40) {
4945                             windialogue = true;
4946                         }
4947                         if (Dialog::currentDialog().type > 49 && Dialog::currentDialog().type < 60) {
4948                             hostile = 1;
4949                             for (unsigned i = 1; i < Person::players.size(); i++) {
4950                                 Person::players[i]->aitype = attacktypecutoff;
4951                             }
4952                         }
4953                     }
4954                 }
4955             }
4956
4957             if (!Person::players[0]->jumpkeydown) {
4958                 Person::players[0]->jumptogglekeydown = 0;
4959             }
4960             if (Person::players[0]->jumpkeydown &&
4961                     Person::players[0]->animTarget != jumpupanim &&
4962                     Person::players[0]->animTarget != jumpdownanim &&
4963                     !Person::players[0]->isFlip())
4964                 Person::players[0]->jumptogglekeydown = 1;
4965
4966
4967             Dialog::dialoguetime += multiplier;
4968             hawkyaw += multiplier * 25;
4969             realhawkcoords = 0;
4970             realhawkcoords.x = 25;
4971             realhawkcoords = DoRotation(realhawkcoords, 0, hawkyaw, 0) + hawkcoords;
4972             hawkcalldelay -= multiplier / 2;
4973
4974             if (hawkcalldelay <= 0) {
4975                 emit_sound_at(hawksound, realhawkcoords);
4976
4977                 hawkcalldelay = 16 + abs(Random() % 8);
4978             }
4979
4980             doDevKeys();
4981
4982             doAttacks();
4983
4984             doPlayerCollisions();
4985
4986             doJumpReversals();
4987
4988             for (unsigned k = 0; k < Person::players.size(); k++)
4989                 if (k != 0 && Person::players[k]->immobile)
4990                     Person::players[k]->coords = Person::players[k]->realoldcoords;
4991
4992             for (unsigned k = 0; k < Person::players.size(); k++) {
4993                 if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
4994                     if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
4995                         Person::players[k]->DoDamage(1000);
4996                     }
4997                 }
4998             }
4999
5000             //respawn
5001             static bool respawnkeydown;
5002             if (!editorenabled &&
5003                     (whichlevel != -2 &&
5004                      (Input::isKeyDown(SDL_SCANCODE_Z) &&
5005                       Input::isKeyDown(SDL_SCANCODE_LGUI) &&
5006                       devtools) ||
5007                      (Input::isKeyDown(jumpkey) &&
5008                       !respawnkeydown &&
5009                       !oldattackkey &&
5010                       Person::players[0]->dead))) {
5011                 targetlevel = whichlevel;
5012                 loading = 1;
5013                 leveltime = 5;
5014             }
5015             respawnkeydown = Input::isKeyDown(jumpkey);
5016
5017
5018             static bool movekey;
5019
5020             //?
5021             for (unsigned i = 0; i < Person::players.size(); i++) {
5022                 static float oldtargetyaw;
5023                 if (!Person::players[i]->skeleton.free) {
5024                     oldtargetyaw = Person::players[i]->targetyaw;
5025                     if (i == 0 && !Dialog::inDialog()) {
5026                         //TODO: refactor repetitive code
5027                         if (!Animation::animations[Person::players[0]->animTarget].attack &&
5028                                 Person::players[0]->animTarget != staggerbackhighanim &&
5029                                 Person::players[0]->animTarget != staggerbackhardanim &&
5030                                 Person::players[0]->animTarget != crouchremoveknifeanim &&
5031                                 Person::players[0]->animTarget != removeknifeanim &&
5032                                 Person::players[0]->animTarget != backhandspringanim &&
5033                                 Person::players[0]->animTarget != dodgebackanim &&
5034                                 Person::players[0]->animTarget != walljumprightkickanim &&
5035                                 Person::players[0]->animTarget != walljumpleftkickanim) {
5036                             if (cameramode)
5037                                 Person::players[0]->targetyaw = 0;
5038                             else
5039                                 Person::players[0]->targetyaw = -yaw + 180;
5040                         }
5041
5042                         facing = 0;
5043                         facing.z = -1;
5044
5045                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
5046                         if (cameramode) {
5047                             facing = flatfacing;
5048                         } else {
5049                             facing = DoRotation(facing, -pitch, 0, 0);
5050                             facing = DoRotation(facing, 0, 0 - yaw, 0);
5051                         }
5052
5053                         Person::players[0]->lookyaw = -yaw;
5054
5055                         Person::players[i]->targetheadyaw = yaw;
5056                         Person::players[i]->targetheadpitch = pitch;
5057                     }
5058                     if (i != 0 && Person::players[i]->aitype == playercontrolled && !Dialog::inDialog()) {
5059                         if (!Animation::animations[Person::players[i]->animTarget].attack &&
5060                                 Person::players[i]->animTarget != staggerbackhighanim &&
5061                                 Person::players[i]->animTarget != staggerbackhardanim &&
5062                                 Person::players[i]->animTarget != crouchremoveknifeanim &&
5063                                 Person::players[i]->animTarget != removeknifeanim &&
5064                                 Person::players[i]->animTarget != backhandspringanim &&
5065                                 Person::players[i]->animTarget != dodgebackanim &&
5066                                 Person::players[i]->animTarget != walljumprightkickanim &&
5067                                 Person::players[i]->animTarget != walljumpleftkickanim) {
5068                             Person::players[i]->targetyaw = -Person::players[i]->lookyaw + 180;
5069                         }
5070
5071                         facing = 0;
5072                         facing.z = -1;
5073
5074                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
5075
5076                         facing = DoRotation(facing, -Person::players[i]->lookpitch, 0, 0);
5077                         facing = DoRotation(facing, 0, 0 - Person::players[i]->lookyaw, 0);
5078
5079                         Person::players[i]->targetheadyaw = Person::players[i]->lookyaw;
5080                         Person::players[i]->targetheadpitch = Person::players[i]->lookpitch;
5081                     }
5082                     if (Dialog::inDialog()) {
5083                         Person::players[i]->targetheadyaw = 180 - roughDirection(Dialog::currentScene().participantfacing[i]);
5084                         Person::players[i]->targetheadpitch = pitchOf(Dialog::currentScene().participantfacing[i]);
5085                     }
5086
5087                     if (leveltime < .5)
5088                         numenvsounds = 0;
5089
5090                     Person::players[i]->avoidsomething = 0;
5091
5092                     //avoid flaming things
5093                     for (int j = 0; j < objects.numobjects; j++)
5094                         if (objects.onfire[j])
5095                             if (distsq(&Person::players[i]->coords, &objects.position[j]) < sq(objects.scale[j]) * 200)
5096                                 if (     distsq(&Person::players[i]->coords, &objects.position[j]) <
5097                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
5098                                     Person::players[i]->collided = 0;
5099                                     Person::players[i]->avoidcollided = 1;
5100                                     if (Person::players[i]->avoidsomething == 0 ||
5101                                             distsq(&Person::players[i]->coords, &objects.position[j]) <
5102                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
5103                                         Person::players[i]->avoidwhere = objects.position[j];
5104                                         Person::players[i]->avoidsomething = 1;
5105                                     }
5106                                 }
5107
5108                     //avoid flaming players
5109                     for (unsigned j = 0; j < Person::players.size(); j++)
5110                         if (Person::players[j]->onfire)
5111                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < sq(0.3) * 200)
5112                                 if (     distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
5113                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
5114                                     Person::players[i]->collided = 0;
5115                                     Person::players[i]->avoidcollided = 1;
5116                                     if (Person::players[i]->avoidsomething == 0 ||
5117                                             distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
5118                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
5119                                         Person::players[i]->avoidwhere = Person::players[j]->coords;
5120                                         Person::players[i]->avoidsomething = 1;
5121                                     }
5122                                 }
5123
5124                     if (Person::players[i]->collided > .8)
5125                         Person::players[i]->avoidcollided = 0;
5126
5127                     doAI(i);
5128
5129                     if (Animation::animations[Person::players[i]->animTarget].attack == reversed) {
5130                         //Person::players[i]->targetyaw=Person::players[i]->yaw;
5131                         Person::players[i]->forwardkeydown = 0;
5132                         Person::players[i]->leftkeydown = 0;
5133                         Person::players[i]->backkeydown = 0;
5134                         Person::players[i]->rightkeydown = 0;
5135                         Person::players[i]->jumpkeydown = 0;
5136                         Person::players[i]->attackkeydown = 0;
5137                         //Person::players[i]->crouchkeydown=0;
5138                         Person::players[i]->throwkeydown = 0;
5139                     }
5140
5141                     if (Dialog::inDialog()) {
5142                         Person::players[i]->forwardkeydown = 0;
5143                         Person::players[i]->leftkeydown = 0;
5144                         Person::players[i]->backkeydown = 0;
5145                         Person::players[i]->rightkeydown = 0;
5146                         Person::players[i]->jumpkeydown = 0;
5147                         Person::players[i]->crouchkeydown = 0;
5148                         Person::players[i]->drawkeydown = 0;
5149                         Person::players[i]->throwkeydown = 0;
5150                     }
5151
5152                     if (Person::players[i]->collided < -.3)
5153                         Person::players[i]->collided = -.3;
5154                     if (Person::players[i]->collided > 1)
5155                         Person::players[i]->collided = 1;
5156                     Person::players[i]->collided -= multiplier * 4;
5157                     Person::players[i]->whichdirectiondelay -= multiplier;
5158                     if (Person::players[i]->avoidcollided < -.3 || Person::players[i]->whichdirectiondelay <= 0) {
5159                         Person::players[i]->avoidcollided = -.3;
5160                         Person::players[i]->whichdirection = abs(Random() % 2);
5161                         Person::players[i]->whichdirectiondelay = .4;
5162                     }
5163                     if (Person::players[i]->avoidcollided > 1)
5164                         Person::players[i]->avoidcollided = 1;
5165                     Person::players[i]->avoidcollided -= multiplier / 4;
5166                     if (!Person::players[i]->skeleton.free) {
5167                         Person::players[i]->stunned -= multiplier;
5168                         Person::players[i]->surprised -= multiplier;
5169                     }
5170                     if (i != 0 && Person::players[i]->surprised <= 0 &&
5171                             Person::players[i]->aitype == attacktypecutoff &&
5172                             !Person::players[i]->dead &&
5173                             !Person::players[i]->skeleton.free &&
5174                             Animation::animations[Person::players[i]->animTarget].attack == neutral)
5175                         numresponded = 1;
5176
5177                     if (!Person::players[i]->throwkeydown)
5178                         Person::players[i]->throwtogglekeydown = 0;
5179
5180                     //pick up weapon
5181                     if (Person::players[i]->throwkeydown && !Person::players[i]->throwtogglekeydown) {
5182                         if (Person::players[i]->weaponactive == -1 &&
5183                                 Person::players[i]->num_weapons < 2 &&
5184                                 (Person::players[i]->isIdle() ||
5185                                  Person::players[i]->isCrouch() ||
5186                                  Person::players[i]->animTarget == sneakanim ||
5187                                  Person::players[i]->animTarget == rollanim ||
5188                                  Person::players[i]->animTarget == backhandspringanim ||
5189                                  Person::players[i]->isFlip() ||
5190                                  Person::players[i]->aitype != playercontrolled)) {
5191                             for (unsigned j = 0; j < weapons.size(); j++) {
5192                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
5193                                         Person::players[i]->aitype == playercontrolled) &&
5194                                         weapons[j].owner == -1 &&
5195                                         Person::players[i]->weaponactive == -1)
5196                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2) {
5197                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 2) {
5198                                             if (Person::players[i]->isCrouch() ||
5199                                                     Person::players[i]->animTarget == sneakanim ||
5200                                                     Person::players[i]->isRun() ||
5201                                                     Person::players[i]->isIdle() ||
5202                                                     Person::players[i]->aitype != playercontrolled) {
5203                                                 Person::players[i]->throwtogglekeydown = 1;
5204                                                 Person::players[i]->setAnimation(crouchremoveknifeanim);
5205                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
5206                                                 Person::players[i]->hasvictim = 0;
5207                                             }
5208                                             if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
5209                                                 Person::players[i]->throwtogglekeydown = 1;
5210                                                 Person::players[i]->hasvictim = 0;
5211
5212                                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
5213                                                         Person::players[i]->aitype == playercontrolled) &&
5214                                                         weapons[j].owner == -1 ||
5215                                                         Person::players[i]->victim &&
5216                                                         weapons[j].owner == int(Person::players[i]->victim->id))
5217                                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2 && Person::players[i]->weaponactive == -1)
5218                                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 1 || Person::players[i]->victim) {
5219                                                             if (weapons[j].getType() != staff)
5220                                                                 emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
5221
5222                                                             Person::players[i]->takeWeapon(j);
5223                                                         }
5224                                             }
5225                                         } else if ((Person::players[i]->isIdle() ||
5226                                                     Person::players[i]->isFlip() ||
5227                                                     Person::players[i]->aitype != playercontrolled) &&
5228                                                    distsq(&Person::players[i]->coords, &weapons[j].position) < 5 &&
5229                                                    Person::players[i]->coords.y < weapons[j].position.y) {
5230                                             if (!Person::players[i]->isFlip()) {
5231                                                 Person::players[i]->throwtogglekeydown = 1;
5232                                                 Person::players[i]->setAnimation(removeknifeanim);
5233                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
5234                                             }
5235                                             if (Person::players[i]->isFlip()) {
5236                                                 Person::players[i]->throwtogglekeydown = 1;
5237                                                 Person::players[i]->hasvictim = 0;
5238
5239                                                 for (unsigned k = 0; k < weapons.size(); k++) {
5240                                                     if (Person::players[i]->weaponactive == -1)
5241                                                         if ((weapons[k].velocity.x == 0 && weapons[k].velocity.y == 0 && weapons[k].velocity.z == 0 ||
5242                                                                 Person::players[i]->aitype == playercontrolled) &&
5243                                                                 weapons[k].owner == -1 ||
5244                                                                 Person::players[i]->victim &&
5245                                                                 weapons[k].owner == int(Person::players[i]->victim->id))
5246                                                             if (distsqflat(&Person::players[i]->coords, &weapons[k].position) < 3 &&
5247                                                                     Person::players[i]->weaponactive == -1) {
5248                                                                 if (weapons[k].getType() != staff)
5249                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
5250
5251                                                                 Person::players[i]->takeWeapon(k);
5252                                                             }
5253                                                 }
5254                                             }
5255                                         }
5256                                     }
5257                             }
5258                             if (Person::players[i]->isCrouch() ||
5259                                     Person::players[i]->animTarget == sneakanim ||
5260                                     Person::players[i]->isRun() ||
5261                                     Person::players[i]->isIdle() || Person::players[i]->animTarget == rollanim ||
5262                                     Person::players[i]->animTarget == backhandspringanim) {
5263                                 if (Person::players.size() > 1)
5264                                     for (unsigned j = 0; j < Person::players.size(); j++) {
5265                                         if (Person::players[i]->weaponactive == -1)
5266                                             if (j != i)
5267                                                 if (Person::players[j]->num_weapons &&
5268                                                         Person::players[j]->skeleton.free &&
5269                                                         distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 2/*&&Person::players[j]->dead*/ &&
5270                                                         (((Person::players[j]->skeleton.forward.y < 0 &&
5271                                                            Person::players[j]->weaponstuckwhere == 0) ||
5272                                                           (Person::players[j]->skeleton.forward.y > 0 &&
5273                                                            Person::players[j]->weaponstuckwhere == 1)) ||
5274                                                          Person::players[j]->weaponstuck == -1 ||
5275                                                          Person::players[j]->num_weapons > 1)) {
5276                                                     if (Person::players[i]->animTarget != rollanim && Person::players[i]->animTarget != backhandspringanim) {
5277                                                         Person::players[i]->throwtogglekeydown = 1;
5278                                                         Person::players[i]->victim = Person::players[j];
5279                                                         Person::players[i]->hasvictim = 1;
5280                                                         Person::players[i]->setAnimation(crouchremoveknifeanim);
5281                                                         Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
5282                                                     }
5283                                                     if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
5284                                                         Person::players[i]->throwtogglekeydown = 1;
5285                                                         Person::players[i]->victim = Person::players[j];
5286                                                         Person::players[i]->hasvictim = 1;
5287                                                         int k = Person::players[j]->weaponids[0];
5288                                                         if (Person::players[i]->hasvictim) {
5289                                                             bool fleshstuck;
5290                                                             fleshstuck = 0;
5291                                                             if (Person::players[i]->victim->weaponstuck != -1) {
5292                                                                 if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
5293                                                                     fleshstuck = 1;
5294                                                                 }
5295                                                             }
5296                                                             if (!fleshstuck) {
5297                                                                 if (weapons[k].getType() != staff)
5298                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
5299                                                             }
5300                                                             if (fleshstuck)
5301                                                                 emit_sound_at(fleshstabremovesound, Person::players[i]->coords, 128.);
5302
5303                                                             if (weapons[k].owner != -1) {
5304                                                                 if (Person::players[i]->victim->num_weapons == 1)
5305                                                                     Person::players[i]->victim->num_weapons = 0;
5306                                                                 else
5307                                                                     Person::players[i]->victim->num_weapons = 1;
5308
5309                                                                 Person::players[i]->victim->skeleton.longdead = 0;
5310                                                                 Person::players[i]->victim->skeleton.free = 1;
5311                                                                 Person::players[i]->victim->skeleton.broken = 0;
5312
5313                                                                 for (int l = 0; l < Person::players[i]->victim->skeleton.joints.size(); l++) {
5314                                                                     Person::players[i]->victim->skeleton.joints[l].velchange = 0;
5315                                                                     Person::players[i]->victim->skeleton.joints[l].locked = 0;
5316                                                                 }
5317
5318                                                                 XYZ relative;
5319                                                                 relative = 0;
5320                                                                 relative.y = 10;
5321                                                                 Normalise(&relative);
5322                                                                 XYZ footvel, footpoint;
5323                                                                 footvel = 0;
5324                                                                 footpoint = weapons[k].position;
5325                                                                 if (Person::players[i]->victim->weaponstuck != -1) {
5326                                                                     if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
5327                                                                         if (bloodtoggle)
5328                                                                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
5329                                                                         weapons[k].bloody = 2;
5330                                                                         weapons[k].blooddrip = 5;
5331                                                                         Person::players[i]->victim->weaponstuck = -1;
5332                                                                         Person::players[i]->victim->bloodloss += 2000;
5333                                                                         Person::players[i]->victim->DoDamage(2000);
5334                                                                     }
5335                                                                 }
5336                                                                 if (Person::players[i]->victim->num_weapons > 0) {
5337                                                                     if (Person::players[i]->victim->weaponstuck != 0 && Person::players[i]->victim->weaponstuck != -1)
5338                                                                         Person::players[i]->victim->weaponstuck = 0;
5339                                                                     if (Person::players[i]->victim->weaponids[0] == k)
5340                                                                         Person::players[i]->victim->weaponids[0] = Person::players[i]->victim->weaponids[Person::players[i]->victim->num_weapons];
5341                                                                 }
5342
5343                                                                 Person::players[i]->victim->weaponactive = -1;
5344
5345                                                                 Person::players[i]->victim->jointVel(abdomen) += relative * 6;
5346                                                                 Person::players[i]->victim->jointVel(neck) += relative * 6;
5347                                                                 Person::players[i]->victim->jointVel(rightshoulder) += relative * 6;
5348                                                                 Person::players[i]->victim->jointVel(leftshoulder) += relative * 6;
5349                                                             }
5350                                                             Person::players[i]->takeWeapon(k);
5351                                                         }
5352                                                     }
5353                                                 }
5354                                     }
5355                             }
5356                         }
5357                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
5358                             if (weapons[Person::players[i]->weaponids[0]].getType() == knife) {
5359                                 if (Person::players[i]->isIdle() ||
5360                                         Person::players[i]->isRun() ||
5361                                         Person::players[i]->isCrouch() ||
5362                                         Person::players[i]->animTarget == sneakanim ||
5363                                         Person::players[i]->isFlip())
5364                                     if (Person::players.size() > 1)
5365                                         for (unsigned j = 0; j < Person::players.size(); j++) {
5366                                             if (i != j)
5367                                                 if (tutoriallevel != 1 || tutorialstage == 49)
5368                                                     if (hostile)
5369                                                         if (normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0 &&
5370                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 100 &&
5371                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) > 1.5 &&
5372                                                                 !Person::players[j]->skeleton.free &&
5373                                                                 -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)) {
5374                                                             if (!Person::players[i]->isFlip()) {
5375                                                                 Person::players[i]->throwtogglekeydown = 1;
5376                                                                 Person::players[i]->victim = Person::players[j];
5377                                                                 Person::players[i]->setAnimation(knifethrowanim);
5378                                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
5379                                                                 Person::players[i]->targettilt2 = pitchTo(Person::players[i]->coords, Person::players[j]->coords);
5380                                                             }
5381                                                             if (Person::players[i]->isFlip()) {
5382                                                                 if (Person::players[i]->weaponactive != -1) {
5383                                                                     Person::players[i]->throwtogglekeydown = 1;
5384                                                                     Person::players[i]->victim = Person::players[j];
5385                                                                     XYZ aim;
5386                                                                     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);
5387                                                                     Normalise(&aim);
5388
5389                                                                     aim = DoRotation(aim, (float)abs(Random() % 30) - 15, (float)abs(Random() % 30) - 15, 0);
5390
5391                                                                     weapons[Person::players[i]->weaponids[0]].thrown(aim * 50, false);
5392                                                                     Person::players[i]->num_weapons--;
5393                                                                     if (Person::players[i]->num_weapons) {
5394                                                                         Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
5395                                                                     }
5396                                                                     Person::players[i]->weaponactive = -1;
5397                                                                 }
5398                                                             }
5399                                                         }
5400                                         }
5401                             }
5402                         }
5403                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
5404                             if (Person::players[i]->isCrouch() || Person::players[i]->animTarget == sneakanim) {
5405                                 Person::players[i]->throwtogglekeydown = 1;
5406                                 XYZ tempVelocity = Person::players[i]->velocity * .2;
5407                                 if (tempVelocity.x == 0)
5408                                     tempVelocity.x = .1;
5409                                 weapons[Person::players[i]->weaponids[0]].drop(tempVelocity, tempVelocity, false);
5410                                 Person::players[i]->num_weapons--;
5411                                 if (Person::players[i]->num_weapons) {
5412                                     Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
5413                                     if (Person::players[i]->weaponstuck == Person::players[i]->num_weapons)
5414                                         Person::players[i]->weaponstuck = 0;
5415                                 }
5416
5417                                 Person::players[i]->weaponactive = -1;
5418                                 for (unsigned j = 0; j < Person::players.size(); j++) {
5419                                     Person::players[j]->wentforweapon = 0;
5420                                 }
5421                             }
5422                         }
5423
5424                     }
5425
5426                     //draw weapon
5427                     if (i == 0 || !Person::players[0]->dead || (Person::players[i]->weaponactive != -1)) {
5428                         if (Person::players[i]->drawkeydown && !Person::players[i]->drawtogglekeydown ||
5429                                 (Person::players[i]->num_weapons == 2) &&
5430                                 (Person::players[i]->weaponactive == -1) &&
5431                                 Person::players[i]->isIdle() ||
5432                                 Person::players[0]->dead &&
5433                                 (Person::players[i]->weaponactive != -1) &&
5434                                 i != 0) {
5435                             bool isgood = true;
5436                             if (Person::players[i]->weaponactive != -1)
5437                                 if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == staff)
5438                                     isgood = false;
5439                             if (isgood && Person::players[i]->creature != wolftype) {
5440                                 if (Person::players[i]->isIdle() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
5441                                     Person::players[i]->setAnimation(drawrightanim);
5442                                     Person::players[i]->drawtogglekeydown = 1;
5443                                 }
5444                                 if ((Person::players[i]->isIdle() ||
5445                                         (Person::players[i]->aitype != playercontrolled &&
5446                                          Person::players[0]->weaponactive != -1 &&
5447                                          Person::players[i]->isRun())) &&
5448                                         Person::players[i]->num_weapons &&
5449                                         weapons[Person::players[i]->weaponids[0]].getType() == sword) {
5450                                     Person::players[i]->setAnimation(drawleftanim);
5451                                     Person::players[i]->drawtogglekeydown = 1;
5452                                 }
5453                                 if (Person::players[i]->isCrouch() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
5454                                     Person::players[i]->setAnimation(crouchdrawrightanim);
5455                                     Person::players[i]->drawtogglekeydown = 1;
5456                                 }
5457                             }
5458                         }
5459                     }
5460
5461                     //clean weapon
5462                     if (Person::players[i]->weaponactive != -1) {
5463                         if (Person::players[i]->isCrouch() &&
5464                                 weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].bloody &&
5465                                 bloodtoggle &&
5466                                 Person::players[i]->onterrain &&
5467                                 Person::players[i]->num_weapons &&
5468                                 Person::players[i]->attackkeydown &&
5469                                 musictype != stream_fighttheme) {
5470                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == knife)
5471                                 Person::players[i]->setAnimation(crouchstabanim);
5472                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == sword)
5473                                 Person::players[i]->setAnimation(swordgroundstabanim);
5474                             Person::players[i]->hasvictim = 0;
5475                         }
5476                     }
5477
5478                     if (!Person::players[i]->drawkeydown)
5479                         Person::players[i]->drawtogglekeydown = 0;
5480
5481                     XYZ absflatfacing;
5482                     if (i == 0) {
5483                         absflatfacing = 0;
5484                         absflatfacing.z = -1;
5485
5486                         absflatfacing = DoRotation(absflatfacing, 0, -yaw, 0);
5487                     } else
5488                         absflatfacing = flatfacing;
5489
5490                     if (Dialog::inDialog()) {
5491                         Person::players[i]->forwardkeydown = 0;
5492                         Person::players[i]->leftkeydown = 0;
5493                         Person::players[i]->backkeydown = 0;
5494                         Person::players[i]->rightkeydown = 0;
5495                         Person::players[i]->jumpkeydown = 0;
5496                         Person::players[i]->crouchkeydown = 0;
5497                         Person::players[i]->drawkeydown = 0;
5498                         Person::players[i]->throwkeydown = 0;
5499                     }
5500                     movekey = 0;
5501                     //Do controls
5502                     if (!Animation::animations[Person::players[i]->animTarget].attack &&
5503                             Person::players[i]->animTarget != staggerbackhighanim &&
5504                             Person::players[i]->animTarget != staggerbackhardanim &&
5505                             Person::players[i]->animTarget != backhandspringanim &&
5506                             Person::players[i]->animTarget != dodgebackanim) {
5507                         if (!Person::players[i]->forwardkeydown)
5508                             Person::players[i]->forwardstogglekeydown = 0;
5509                         if (Person::players[i]->crouchkeydown) {
5510                             //Crouch
5511                             target = -2;
5512                             if (i == 0) {
5513                                 Person::players[i]->superruntoggle = 1;
5514                                 if (Person::players.size() > 1)
5515                                     for (unsigned j = 0; j < Person::players.size(); j++)
5516                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->aitype == passivetype)
5517                                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 16)
5518                                                 Person::players[i]->superruntoggle = 0;
5519                             }
5520
5521                             if (Person::players.size() > 1)
5522                                 for (unsigned j = 0; j < Person::players.size(); j++) {
5523                                     if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim && Person::players[i]->lowreversaldelay <= 0) {
5524                                         if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
5525                                                 Person::players[j]->victim == Person::players[i] &&
5526                                                 (Person::players[j]->animTarget == sweepanim ||
5527                                                  Person::players[j]->animTarget == upunchanim ||
5528                                                  Person::players[j]->animTarget == wolfslapanim ||
5529                                                  ((Person::players[j]->animTarget == swordslashanim ||
5530                                                    Person::players[j]->animTarget == knifeslashstartanim ||
5531                                                    Person::players[j]->animTarget == staffhitanim ||
5532                                                    Person::players[j]->animTarget == staffspinhitanim) &&
5533                                                   distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2))) {
5534                                             if (target >= 0)
5535                                                 target = -1;
5536                                             else
5537                                                 target = j;
5538                                         }
5539                                     }
5540                                 }
5541                             if (target >= 0)
5542                                 Person::players[target]->Reverse();
5543                             Person::players[i]->lowreversaldelay = .5;
5544
5545                             if (Person::players[i]->isIdle()) {
5546                                 Person::players[i]->setAnimation(Person::players[i]->getCrouch());
5547                                 Person::players[i]->transspeed = 10;
5548                             }
5549                             if (Person::players[i]->isRun() ||
5550                                     (Person::players[i]->isStop() &&
5551                                      (Person::players[i]->leftkeydown ||
5552                                       Person::players[i]->rightkeydown ||
5553                                       Person::players[i]->forwardkeydown ||
5554                                       Person::players[i]->backkeydown))) {
5555                                 Person::players[i]->setAnimation(rollanim);
5556                                 Person::players[i]->transspeed = 20;
5557                             }
5558                         }
5559                         if (!Person::players[i]->crouchkeydown) {
5560                             //Uncrouch
5561                             if (!Person::players[i]->isRun() && Person::players[i]->animTarget != sneakanim && i == 0)
5562                                 Person::players[i]->superruntoggle = 0;
5563                             target = -2;
5564                             if (Person::players[i]->isCrouch()) {
5565                                 if (Person::players.size() > 1)
5566                                     for (unsigned j = 0; j < Person::players.size(); j++) {
5567                                         if (j != i &&
5568                                                 !Person::players[j]->skeleton.free &&
5569                                                 Person::players[j]->victim &&
5570                                                 Person::players[i]->highreversaldelay <= 0) {
5571                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
5572                                                     Person::players[j]->victim == Person::players[i] &&
5573                                                     (Person::players[j]->animTarget == spinkickanim) &&
5574                                                     Person::players[i]->isCrouch()) {
5575                                                 if (target >= 0)
5576                                                     target = -1;
5577                                                 else
5578                                                     target = j;
5579                                             }
5580                                         }
5581                                     }
5582                                 if (target >= 0)
5583                                     Person::players[target]->Reverse();
5584                                 Person::players[i]->highreversaldelay = .5;
5585
5586                                 if (Person::players[i]->isCrouch()) {
5587                                     if (!Person::players[i]->wasCrouch()) {
5588                                         Person::players[i]->animCurrent = Person::players[i]->getCrouch();
5589                                         Person::players[i]->frameCurrent = 0;
5590                                     }
5591                                     Person::players[i]->setAnimation(Person::players[i]->getIdle());
5592                                     Person::players[i]->transspeed = 10;
5593                                 }
5594                             }
5595                             if (Person::players[i]->animTarget == sneakanim) {
5596                                 Person::players[i]->setAnimation(Person::players[i]->getIdle());
5597                                 Person::players[i]->transspeed = 10;
5598                             }
5599                         }
5600                         if (Person::players[i]->forwardkeydown) {
5601                             if (Person::players[i]->isIdle() ||
5602                                     (Person::players[i]->isStop() &&
5603                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
5604                                     (Person::players[i]->isLanding() &&
5605                                      Person::players[i]->frameTarget > 0 &&
5606                                      !Person::players[i]->jumpkeydown) ||
5607                                     (Person::players[i]->isLandhard() &&
5608                                      Person::players[i]->frameTarget > 0 &&
5609                                      !Person::players[i]->jumpkeydown &&
5610                                      Person::players[i]->crouchkeydown)) {
5611                                 if (Person::players[i]->aitype == passivetype)
5612                                     Person::players[i]->setAnimation(walkanim);
5613                                 else
5614                                     Person::players[i]->setAnimation(Person::players[i]->getRun());
5615                             }
5616                             if (Person::players[i]->isCrouch()) {
5617                                 Person::players[i]->animTarget = sneakanim;
5618                                 if (Person::players[i]->wasCrouch())
5619                                     Person::players[i]->target = 0;
5620                                 Person::players[i]->frameTarget = 0;
5621                             }
5622                             if (Person::players[i]->animTarget == hanganim/*&&(!Person::players[i]->forwardstogglekeydown||Person::players[i]->aitype!=playercontrolled)*/) {
5623                                 Person::players[i]->setAnimation(climbanim);
5624                                 Person::players[i]->frameTarget = 1;
5625                                 Person::players[i]->jumpclimb = 1;
5626                             }
5627                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
5628                                 Person::players[i]->velocity += absflatfacing * 5 * multiplier;
5629                             }
5630                             Person::players[i]->forwardstogglekeydown = 1;
5631                             movekey = 1;
5632                         }
5633                         if (Person::players[i]->rightkeydown) {
5634                             if (Person::players[i]->isIdle() ||
5635                                     (Person::players[i]->isStop() &&
5636                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
5637                                     (Person::players[i]->isLanding() &&
5638                                      Person::players[i]->frameTarget > 0 &&
5639                                      !Person::players[i]->jumpkeydown) ||
5640                                     (Person::players[i]->isLandhard() &&
5641                                      Person::players[i]->frameTarget > 0 &&
5642                                      !Person::players[i]->jumpkeydown &&
5643                                      Person::players[i]->crouchkeydown)) {
5644                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
5645                             }
5646                             if (Person::players[i]->isCrouch()) {
5647                                 Person::players[i]->animTarget = sneakanim;
5648                                 if (Person::players[i]->wasCrouch())
5649                                     Person::players[i]->target = 0;
5650                                 Person::players[i]->frameTarget = 0;
5651                             }
5652                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
5653                                 Person::players[i]->velocity += DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
5654                             }
5655                             Person::players[i]->targetyaw -= 90;
5656                             if (Person::players[i]->forwardkeydown)
5657                                 Person::players[i]->targetyaw += 45;
5658                             if (Person::players[i]->backkeydown)
5659                                 Person::players[i]->targetyaw -= 45;
5660                             movekey = 1;
5661                         }
5662                         if ( Person::players[i]->leftkeydown) {
5663                             if (Person::players[i]->isIdle() ||
5664                                     (Person::players[i]->isStop() &&
5665                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
5666                                     (Person::players[i]->isLanding() &&
5667                                      Person::players[i]->frameTarget > 0 &&
5668                                      !Person::players[i]->jumpkeydown) ||
5669                                     (Person::players[i]->isLandhard() &&
5670                                      Person::players[i]->frameTarget > 0 &&
5671                                      !Person::players[i]->jumpkeydown &&
5672                                      Person::players[i]->crouchkeydown)) {
5673                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
5674                             }
5675                             if (Person::players[i]->isCrouch()) {
5676                                 Person::players[i]->animTarget = sneakanim;
5677                                 if (Person::players[i]->wasCrouch())
5678                                     Person::players[i]->target = 0;
5679                                 Person::players[i]->frameTarget = 0;
5680                             }
5681                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
5682                                 Person::players[i]->velocity -= DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
5683                             }
5684                             Person::players[i]->targetyaw += 90;
5685                             if (Person::players[i]->forwardkeydown)
5686                                 Person::players[i]->targetyaw -= 45;
5687                             if (Person::players[i]->backkeydown)
5688                                 Person::players[i]->targetyaw += 45;
5689                             movekey = 1;
5690                         }
5691                         if (Person::players[i]->backkeydown) {
5692                             if (Person::players[i]->isIdle() ||
5693                                     (Person::players[i]->isStop() &&
5694                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
5695                                     (Person::players[i]->isLanding() &&
5696                                      Person::players[i]->frameTarget > 0 &&
5697                                      !Person::players[i]->jumpkeydown) ||
5698                                     (Person::players[i]->isLandhard() &&
5699                                      Person::players[i]->frameTarget > 0 &&
5700                                      !Person::players[i]->jumpkeydown &&
5701                                      Person::players[i]->crouchkeydown)) {
5702                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
5703                             }
5704                             if (Person::players[i]->isCrouch()) {
5705                                 Person::players[i]->animTarget = sneakanim;
5706                                 if (Person::players[i]->wasCrouch())
5707                                     Person::players[i]->target = 0;
5708                                 Person::players[i]->frameTarget = 0;
5709                             }
5710                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
5711                                 Person::players[i]->velocity -= absflatfacing * 5 * multiplier;
5712                             }
5713                             if (Person::players[i]->animTarget == hanganim) {
5714                                 Person::players[i]->animCurrent = jumpdownanim;
5715                                 Person::players[i]->animTarget = jumpdownanim;
5716                                 Person::players[i]->target = 0;
5717                                 Person::players[i]->frameCurrent = 0;
5718                                 Person::players[i]->frameTarget = 1;
5719                                 Person::players[i]->velocity = 0;
5720                                 Person::players[i]->velocity.y += gravity;
5721                                 Person::players[i]->coords.y -= 1.4;
5722                                 Person::players[i]->grabdelay = 1;
5723                             }
5724                             if ( !Person::players[i]->leftkeydown && !Person::players[i]->rightkeydown)
5725                                 Person::players[i]->targetyaw += 180;
5726                             movekey = 1;
5727                         }
5728                         if ((Person::players[i]->jumpkeydown && !Person::players[i]->jumpclimb) || Person::players[i]->jumpstart) {
5729                             if ((((Person::players[i]->isLanding() && Person::players[i]->frameTarget >= 3) ||
5730                                     Person::players[i]->isRun() ||
5731                                     Person::players[i]->animTarget == walkanim ||
5732                                     Person::players[i]->isCrouch() ||
5733                                     Person::players[i]->animTarget == sneakanim) &&
5734                                     Person::players[i]->jumppower > 1) &&
5735                                     ((Person::players[i]->animTarget != rabbitrunninganim &&
5736                                       Person::players[i]->animTarget != wolfrunninganim) || i != 0)) {
5737                                 Person::players[i]->jumpstart = 0;
5738                                 Person::players[i]->setAnimation(jumpupanim);
5739                                 Person::players[i]->yaw = Person::players[i]->targetyaw;
5740                                 Person::players[i]->transspeed = 20;
5741                                 Person::players[i]->FootLand(leftfoot, 1);
5742                                 Person::players[i]->FootLand(rightfoot, 1);
5743
5744                                 facing = 0;
5745                                 facing.z = -1;
5746                                 flatfacing = DoRotation(facing, 0, Person::players[i]->targetyaw + 180, 0);
5747
5748                                 if (movekey)
5749                                     Person::players[i]->velocity = flatfacing * Person::players[i]->speed * 45 * Person::players[i]->scale;
5750                                 if (!movekey)
5751                                     Person::players[i]->velocity = 0;
5752
5753                                 //Dodge sweep?
5754                                 target = -2;
5755                                 if (Person::players.size() > 1)
5756                                     for (unsigned j = 0; j < Person::players.size(); j++) {
5757                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim) {
5758                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
5759                                                     (Person::players[j]->victim == Person::players[i]) &&
5760                                                     (Person::players[j]->animTarget == sweepanim)) {
5761                                                 if (target >= 0)
5762                                                     target = -1;
5763                                                 else
5764                                                     target = j;
5765                                             }
5766                                         }
5767                                     }
5768                                 if (target >= 0)
5769                                     Person::players[i]->velocity.y = 1;
5770                                 else
5771                                     if (Person::players[i]->crouchkeydown || Person::players[i]->aitype != playercontrolled) {
5772                                     Person::players[i]->velocity.y = 7;
5773                                     Person::players[i]->crouchtogglekeydown = 1;
5774                                 } else Person::players[i]->velocity.y = 5;
5775
5776                                 if (mousejump && i == 0 && devtools) {
5777                                     if (!Person::players[i]->isLanding())
5778                                         Person::players[i]->tempdeltav = deltav;
5779                                     if (Person::players[i]->tempdeltav < 0)
5780                                         Person::players[i]->velocity.y -= (float)(Person::players[i]->tempdeltav) / multiplier / 1000;
5781                                 }
5782
5783                                 Person::players[i]->coords.y += .2;
5784                                 Person::players[i]->jumppower -= 1;
5785
5786                                 if (!i)
5787                                     emit_sound_at(whooshsound, Person::players[i]->coords, 128.);
5788
5789                                 emit_sound_at(jumpsound, Person::players[i]->coords, 128.);
5790                             }
5791                             if ((Person::players[i]->isIdle()) && Person::players[i]->jumppower > 1) {
5792                                 Person::players[i]->setAnimation(Person::players[i]->getLanding());
5793                                 Person::players[i]->frameTarget = 2;
5794                                 Person::players[i]->landhard = 0;
5795                                 Person::players[i]->jumpstart = 1;
5796                                 Person::players[i]->tempdeltav = deltav;
5797                             }
5798                             if (Person::players[i]->animTarget == jumpupanim &&
5799                                     (((!floatjump &&
5800                                        !editorenabled) ||
5801                                       !devtools) ||
5802                                      Person::players[i]->aitype != playercontrolled)) {
5803                                 if (Person::players[i]->jumppower > multiplier * 6) {
5804                                     Person::players[i]->velocity.y += multiplier * 6;
5805                                     Person::players[i]->jumppower -= multiplier * 6;
5806                                 }
5807                                 if (Person::players[i]->jumppower <= multiplier * 6) {
5808                                     Person::players[i]->velocity.y += Person::players[i]->jumppower;
5809                                     Person::players[i]->jumppower = 0;
5810                                 }
5811                             }
5812                             if (((floatjump || editorenabled) && devtools) && i == 0)
5813                                 Person::players[i]->velocity.y += multiplier * 30;
5814                         }
5815
5816                         if (!movekey) {
5817                             if (Person::players[i]->isRun() || Person::players[i]->animTarget == walkanim)
5818                                 Person::players[i]->setAnimation(Person::players[i]->getStop());
5819                             if (Person::players[i]->animTarget == sneakanim) {
5820                                 Person::players[i]->animTarget = Person::players[i]->getCrouch();
5821                                 if (Person::players[i]->animCurrent == sneakanim)
5822                                     Person::players[i]->target = 0;
5823                                 Person::players[i]->frameTarget = 0;
5824                             }
5825                         }
5826                         if (Person::players[i]->animTarget == walkanim &&
5827                                 (Person::players[i]->aitype == attacktypecutoff ||
5828                                  Person::players[i]->aitype == searchtype ||
5829                                  (Person::players[i]->aitype == passivetype &&
5830                                   Person::players[i]->numwaypoints <= 1)))
5831                             Person::players[i]->setAnimation(Person::players[i]->getStop());
5832                         if (Person::players[i]->isRun() && (Person::players[i]->aitype == passivetype))
5833                             Person::players[i]->setAnimation(Person::players[i]->getStop());
5834                     }
5835                 }
5836                 if (Person::players[i]->animTarget == rollanim)
5837                     Person::players[i]->targetyaw = oldtargetyaw;
5838             }
5839
5840             //Rotation
5841             for (unsigned k = 0; k < Person::players.size(); k++) {
5842                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 180) {
5843                     if (Person::players[k]->yaw > Person::players[k]->targetyaw)
5844                         Person::players[k]->yaw -= 360;
5845                     else
5846                         Person::players[k]->yaw += 360;
5847                 }
5848
5849                 //stop to turn in right direction
5850                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 90 && (Person::players[k]->isRun() || Person::players[k]->animTarget == walkanim))
5851                     Person::players[k]->setAnimation(Person::players[k]->getStop());
5852
5853                 if (Person::players[k]->animTarget == backhandspringanim || Person::players[k]->animTarget == dodgebackanim)
5854                     Person::players[k]->targettilt = 0;
5855
5856                 if (Person::players[k]->animTarget != jumpupanim &&
5857                         Person::players[k]->animTarget != backhandspringanim &&
5858                         Person::players[k]->animTarget != jumpdownanim &&
5859                         !Person::players[k]->isFlip()) {
5860                     Person::players[k]->targettilt = 0;
5861                     if (Person::players[k]->jumppower < 0 && !Person::players[k]->jumpkeydown)
5862                         Person::players[k]->jumppower = 0;
5863                     Person::players[k]->jumppower += multiplier * 7;
5864                     if (Person::players[k]->isCrouch())
5865                         Person::players[k]->jumppower += multiplier * 7;
5866                     if (Person::players[k]->jumppower > 5)
5867                         Person::players[k]->jumppower = 5;
5868                 }
5869
5870                 if (Person::players[k]->isRun())
5871                     Person::players[k]->targettilt = (Person::players[k]->yaw - Person::players[k]->targetyaw) / 4;
5872
5873                 Person::players[k]->tilt = stepTowardf(Person::players[k]->tilt, Person::players[k]->targettilt, multiplier * 150);
5874                 Person::players[k]->grabdelay -= multiplier;
5875             }
5876
5877             //do animations
5878             for (unsigned k = 0; k < Person::players.size(); k++) {
5879                 Person::players[k]->DoAnimations();
5880                 Person::players[k]->whichpatchx = Person::players[k]->coords.x / (terrain.size / subdivision * terrain.scale);
5881                 Person::players[k]->whichpatchz = Person::players[k]->coords.z / (terrain.size / subdivision * terrain.scale);
5882             }
5883
5884             //do stuff
5885             objects.DoStuff();
5886
5887             for (int j = numenvsounds - 1; j >= 0; j--) {
5888                 envsoundlife[j] -= multiplier;
5889                 if (envsoundlife[j] < 0) {
5890                     numenvsounds--;
5891                     envsoundlife[j] = envsoundlife[numenvsounds];
5892                     envsound[j] = envsound[numenvsounds];
5893                 }
5894             }
5895             OPENAL_SetFrequency(OPENAL_ALL, slomo);
5896
5897             if (tutoriallevel == 1) {
5898                 XYZ temp;
5899                 XYZ temp2;
5900                 XYZ temp3;
5901                 XYZ oldtemp;
5902                 XYZ oldtemp2;
5903                 temp.x = 1011;
5904                 temp.y = 84;
5905                 temp.z = 491;
5906                 temp2.x = 1025;
5907                 temp2.y = 75;
5908                 temp2.z = 447;
5909                 temp3.x = 1038;
5910                 temp3.y = 76;
5911                 temp3.z = 453;
5912                 oldtemp = temp;
5913                 oldtemp2 = temp2;
5914                 if (tutorialstage >= 51)
5915                     if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
5916                         OPENAL_StopSound(OPENAL_ALL);  // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
5917                         OPENAL_SetFrequency(OPENAL_ALL);
5918
5919                         emit_stream_np(stream_menutheme);
5920
5921                         gameon = 0;
5922                         mainmenu = 5;
5923
5924                         fireSound();
5925
5926                         flash();
5927                     }
5928                 if (tutorialstage < 51)
5929                     if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
5930                         emit_sound_at(fireendsound, Person::players[0]->coords);
5931
5932                         Person::players[0]->coords = (oldtemp + oldtemp2) / 2;
5933
5934                         flash();
5935                     }
5936                 if (tutorialstage >= 14 && tutorialstage < 50)
5937                     if (distsq(&temp, &Person::players[1]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[1]->coords) < 4) {
5938                         emit_sound_at(fireendsound, Person::players[1]->coords);
5939
5940                         for (int i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
5941                             if (Random() % 2 == 0) {
5942                                 if (!Person::players[1]->skeleton.free)
5943                                     temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
5944                                 if (Person::players[1]->skeleton.free)
5945                                     temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
5946                                 if (!Person::players[1]->skeleton.free)
5947                                     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;
5948                                 if (Person::players[1]->skeleton.free)
5949                                     temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
5950                                 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
5951                             }
5952                         }
5953
5954                         Person::players[1]->coords = (oldtemp + oldtemp2) / 2;
5955                         for (int i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
5956                             Person::players[1]->skeleton.joints[i].velocity = 0;
5957                             if (Random() % 2 == 0) {
5958                                 if (!Person::players[1]->skeleton.free)
5959                                     temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
5960                                 if (Person::players[1]->skeleton.free)
5961                                     temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
5962                                 if (!Person::players[1]->skeleton.free)
5963                                     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;
5964                                 if (Person::players[1]->skeleton.free)
5965                                     temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
5966                                 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
5967                             }
5968                         }
5969                     }
5970             }
5971
5972
5973             //3d sound
5974             static float gLoc[3];
5975             gLoc[0] = viewer.x;
5976             gLoc[1] = viewer.y;
5977             gLoc[2] = viewer.z;
5978             static float vel[3];
5979             vel[0] = (viewer.x - oldviewer.x) / multiplier;
5980             vel[1] = (viewer.y - oldviewer.y) / multiplier;
5981             vel[2] = (viewer.z - oldviewer.z) / multiplier;
5982
5983             //Set orientation with forward and up vectors
5984             static XYZ upvector;
5985             upvector = 0;
5986             upvector.z = -1;
5987
5988             upvector = DoRotation(upvector, -pitch + 90, 0, 0);
5989             upvector = DoRotation(upvector, 0, 0 - yaw, 0);
5990
5991             facing = 0;
5992             facing.z = -1;
5993
5994             facing = DoRotation(facing, -pitch, 0, 0);
5995             facing = DoRotation(facing, 0, 0 - yaw, 0);
5996
5997
5998             static float ori[6];
5999             ori[0] = -facing.x;
6000             ori[1] = facing.y;
6001             ori[2] = -facing.z;
6002             ori[3] = -upvector.x;
6003             ori[4] = upvector.y;
6004             ori[5] = -upvector.z;
6005
6006             OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
6007             OPENAL_Update();
6008
6009             oldviewer = viewer;
6010         }
6011     }
6012
6013     if (Input::isKeyPressed(SDL_SCANCODE_F1))
6014         Screenshot();
6015 }
6016
6017 void Game::TickOnce()
6018 {
6019     if (mainmenu) {
6020         yaw += multiplier * 5;
6021     } else if (Dialog::directing || !Dialog::inDialog()) {
6022         yaw += deltah * .7;
6023         if (invertmouse) {
6024             pitch -= deltav * .7;
6025         } else {
6026             pitch += deltav * .7;
6027         }
6028         if (pitch > 90)
6029             pitch = 90;
6030         if (pitch < -70)
6031             pitch = -70;
6032     }
6033 }
6034
6035 void Game::TickOnceAfter()
6036 {
6037     static XYZ colviewer;
6038     static XYZ coltarget;
6039     static XYZ target;
6040     static XYZ col;
6041     static XYZ facing;
6042     static float changedelay;
6043     static bool alldead;
6044     static float unseendelay;
6045     static float cameraspeed;
6046
6047     if (!mainmenu) {
6048         static int oldmusictype = musictype;
6049
6050         if (environment == snowyenvironment)
6051             leveltheme = stream_snowtheme;
6052         if (environment == grassyenvironment)
6053             leveltheme = stream_grasstheme;
6054         if (environment == desertenvironment)
6055             leveltheme = stream_deserttheme;
6056
6057         realthreat = 0;
6058
6059         musictype = leveltheme;
6060         for (unsigned i = 0; i < Person::players.size(); i++) {
6061             if ((Person::players[i]->aitype == attacktypecutoff ||
6062                     Person::players[i]->aitype == getweapontype ||
6063                     Person::players[i]->aitype == gethelptype ||
6064                     Person::players[i]->aitype == searchtype) &&
6065                     !Person::players[i]->dead/*&&Person::players[i]->surprised<=0*/ &&
6066                     (Person::players[i]->animTarget != sneakattackedanim &&
6067                      Person::players[i]->animTarget != knifesneakattackedanim &&
6068                      Person::players[i]->animTarget != swordsneakattackedanim)) {
6069                 musictype = stream_fighttheme;
6070                 realthreat = 1;
6071             }
6072         }
6073         if (Person::players[0]->dead)
6074             musictype = stream_menutheme;
6075
6076
6077         if (musictype == stream_fighttheme)
6078             unseendelay = 1;
6079
6080         if (oldmusictype == stream_fighttheme && musictype != stream_fighttheme) {
6081             unseendelay -= multiplier;
6082             if (unseendelay > 0)
6083                 musictype = stream_fighttheme;
6084         }
6085
6086
6087         if (loading == 2) {
6088             musictype = stream_menutheme;
6089             musicvolume[2] = 512;
6090             musicvolume[0] = 0;
6091             musicvolume[1] = 0;
6092             musicvolume[3] = 0;
6093         }
6094
6095         if (musictoggle)
6096             if (musictype != oldmusictype && musictype == stream_fighttheme)
6097                 emit_sound_np(alarmsound);
6098         musicselected = musictype;
6099
6100         if (musicselected == leveltheme)
6101             musicvolume[0] += multiplier * 450;
6102         else
6103             musicvolume[0] -= multiplier * 450;
6104         if (musicselected == stream_fighttheme)
6105             musicvolume[1] += multiplier * 450;
6106         else
6107             musicvolume[1] -= multiplier * 450;
6108         if (musicselected == stream_menutheme)
6109             musicvolume[2] += multiplier * 450;
6110         else
6111             musicvolume[2] -= multiplier * 450;
6112
6113         for (int i = 0; i < 3; i++) {
6114             if (musicvolume[i] < 0)
6115                 musicvolume[i] = 0;
6116             if (musicvolume[i] > 512)
6117                 musicvolume[i] = 512;
6118         }
6119
6120         if (musicvolume[2] > 128 && !loading && !mainmenu)
6121             musicvolume[2] = 128;
6122
6123         if (musictoggle) {
6124             if (musicvolume[0] > 0 && oldmusicvolume[0] <= 0)
6125                 emit_stream_np(leveltheme, musicvolume[0]);
6126             if (musicvolume[1] > 0 && oldmusicvolume[1] <= 0)
6127                 emit_stream_np(stream_fighttheme, musicvolume[1]);
6128             if (musicvolume[2] > 0 && oldmusicvolume[2] <= 0)
6129                 emit_stream_np(stream_menutheme, musicvolume[2]);
6130             if (musicvolume[0] <= 0 && oldmusicvolume[0] > 0)
6131                 pause_sound(leveltheme);
6132             if (musicvolume[1] <= 0 && oldmusicvolume[1] > 0)
6133                 pause_sound(stream_fighttheme);
6134             if (musicvolume[2] <= 0 && oldmusicvolume[2] > 0)
6135                 pause_sound(stream_menutheme);
6136
6137             if (musicvolume[0] != oldmusicvolume[0])
6138                 OPENAL_SetVolume(channels[leveltheme], musicvolume[0]);
6139             if (musicvolume[1] != oldmusicvolume[1])
6140                 OPENAL_SetVolume(channels[stream_fighttheme], musicvolume[1]);
6141             if (musicvolume[2] != oldmusicvolume[2])
6142                 OPENAL_SetVolume(channels[stream_menutheme], musicvolume[2]);
6143
6144             for (int i = 0; i < 3; i++)
6145                 oldmusicvolume[i] = musicvolume[i];
6146         } else {
6147             pause_sound(leveltheme);
6148             pause_sound(stream_fighttheme);
6149             pause_sound(stream_menutheme);
6150
6151             for (int i = 0; i < 4; i++) {
6152                 oldmusicvolume[i] = 0;
6153                 musicvolume[i] = 0;
6154             }
6155         }
6156
6157         Hotspot::killhotspot = 2;
6158         for (int i = 0; i < Hotspot::hotspots.size(); i++) {
6159             if (Hotspot::hotspots[i].type > 10 && Hotspot::hotspots[i].type < 20) {
6160                 if (Person::players[Hotspot::hotspots[i].type - 10]->dead == 0)
6161                     Hotspot::killhotspot = 0;
6162                 else if (Hotspot::killhotspot == 2)
6163                     Hotspot::killhotspot = 1;
6164             }
6165         }
6166         if (Hotspot::killhotspot == 2)
6167             Hotspot::killhotspot = 0;
6168
6169
6170         winhotspot = false;
6171         for (int i = 0; i < Hotspot::hotspots.size(); i++)
6172             if (Hotspot::hotspots[i].type == -1)
6173                 if (distsq(&Person::players[0]->coords, &Hotspot::hotspots[i].position) < Hotspot::hotspots[i].size)
6174                     winhotspot = true;
6175
6176         int numalarmed = 0;
6177         for (unsigned i = 1; i < Person::players.size(); i++)
6178             if (!Person::players[i]->dead && Person::players[i]->aitype == attacktypecutoff && Person::players[i]->surprised <= 0)
6179                 numalarmed++;
6180         if (numalarmed > maxalarmed)
6181             maxalarmed = numalarmed;
6182
6183         if (changedelay <= 0 && !loading && !editorenabled && gameon && !tutoriallevel && changedelay != -999 && !won) {
6184             if (Person::players[0]->dead && changedelay <= 0) {
6185                 changedelay = 1;
6186                 targetlevel = whichlevel;
6187             }
6188             alldead = true;
6189             for (unsigned i = 1; i < Person::players.size(); i++) {
6190                 if (!Person::players[i]->dead && Person::players[i]->howactive < typedead1) {
6191                     alldead = false;
6192                     break;
6193                 }
6194             }
6195
6196
6197             if (alldead && !Person::players[0]->dead && maptype == mapkilleveryone) {
6198                 changedelay = 1;
6199                 targetlevel = whichlevel + 1;
6200                 if (targetlevel > numchallengelevels - 1)
6201                     targetlevel = 0;
6202             }
6203             if (winhotspot || windialogue) {
6204                 changedelay = 0.1;
6205                 targetlevel = whichlevel + 1;
6206                 if (targetlevel > numchallengelevels - 1)
6207                     targetlevel = 0;
6208             }
6209
6210
6211             if (Hotspot::killhotspot) {
6212                 changedelay = 1;
6213                 targetlevel = whichlevel + 1;
6214                 if (targetlevel > numchallengelevels - 1)
6215                     targetlevel = 0;
6216             }
6217
6218             if (changedelay > 0 && !Person::players[0]->dead && !won) {
6219                 //high scores, awards, win
6220                 if (campaign) {
6221                     Account::active().winCampaignLevel(whichchoice, bonustotal, leveltime);
6222                     scoreadded = 1;
6223                 } else {
6224                     wonleveltime = leveltime;
6225                     Account::active().winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
6226                 }
6227                 won = 1;
6228             }
6229         }
6230
6231         if (!winfreeze) {
6232
6233             if (leveltime < 1) {
6234                 loading = 0;
6235                 changedelay = .1;
6236                 alldead = false;
6237                 winhotspot = false;
6238                 Hotspot::killhotspot = 0;
6239             }
6240
6241             if (!editorenabled && gameon && !mainmenu) {
6242                 if (changedelay != -999)
6243                     changedelay -= multiplier / 7;
6244                 if (Person::players[0]->dead)
6245                     targetlevel = whichlevel;
6246                 if (loading == 2 && !campaign) {
6247                     flash();
6248
6249                     fireSound(firestartsound);
6250
6251                     if (!Person::players[0]->dead && targetlevel != whichlevel)
6252                         startbonustotal = bonustotal;
6253                     if (Person::players[0]->dead)
6254                         Loadlevel(whichlevel);
6255                     else
6256                         Loadlevel(targetlevel);
6257
6258                     fireSound();
6259
6260                     loading = 3;
6261                 }
6262                 if (loading == 2 && targetlevel == whichlevel) {
6263                     flash();
6264                     loadtime = 0;
6265
6266                     fireSound(firestartsound);
6267
6268                     Loadlevel(campaignlevels[Account::active().getCampaignChoicesMade()].mapname.c_str());
6269
6270                     fireSound();
6271
6272                     loading = 3;
6273                 }
6274                 if (changedelay <= -999 &&
6275                         whichlevel != -2 &&
6276                         !loading &&
6277                         (Person::players[0]->dead ||
6278                          (alldead && maptype == mapkilleveryone) ||
6279                          (winhotspot) ||
6280                          (Hotspot::killhotspot)))
6281                     loading = 1;
6282                 if ((Person::players[0]->dead ||
6283                         (alldead && maptype == mapkilleveryone) ||
6284                         (winhotspot) ||
6285                         (windialogue) ||
6286                         (Hotspot::killhotspot)) &&
6287                         changedelay <= 0) {
6288                     if (whichlevel != -2 && !loading && !Person::players[0]->dead) {
6289                         winfreeze = true;
6290                         changedelay = -999;
6291                     }
6292                     if (Person::players[0]->dead)
6293                         loading = 1;
6294                 }
6295             }
6296
6297             if (campaign) {
6298                 // campaignchoosenext determines what to do when the level is complete:
6299                 // 0 = load next level
6300                 // 1 = go back to level select screen
6301                 // 2 = stealthload next level
6302                 if (mainmenu == 0 && winfreeze && (campaignlevels[actuallevel].choosenext) == 1) {
6303                     if (campaignlevels[actuallevel].nextlevel.empty())
6304                         endgame = 1;
6305                 } else if (mainmenu == 0 && winfreeze) {
6306                     stealthloading = (campaignlevels[actuallevel].choosenext == 2);
6307
6308                     if (!stealthloading) {
6309                         fireSound(firestartsound);
6310
6311                         flash();
6312                     }
6313
6314                     startbonustotal = 0;
6315
6316                     LoadCampaign();
6317
6318                     loading = 2;
6319                     loadtime = 0;
6320                     targetlevel = 7;
6321                     if (!firstload)
6322                         LoadStuff();
6323                     whichchoice = 0;
6324                     actuallevel = campaignlevels[actuallevel].nextlevel.front();
6325                     visibleloading = 1;
6326                     stillloading = 1;
6327                     Loadlevel(campaignlevels[actuallevel].mapname.c_str());
6328                     campaign = 1;
6329                     mainmenu = 0;
6330                     gameon = 1;
6331                     pause_sound(stream_menutheme);
6332
6333                     stealthloading = 0;
6334                 }
6335             }
6336
6337             if (loading == 3)
6338                 loading = 0;
6339
6340         }
6341
6342         oldmusictype = musictype;
6343     }
6344
6345     facing = 0;
6346     facing.z = -1;
6347
6348     facing = DoRotation(facing, -pitch, 0, 0);
6349     facing = DoRotation(facing, 0, 0 - yaw, 0);
6350     viewerfacing = facing;
6351
6352     if (!cameramode) {
6353         if ((Animation::animations[Person::players[0]->animTarget].attack != 3 && Animation::animations[Person::players[0]->animCurrent].attack != 3) || Person::players[0]->skeleton.free)
6354             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;
6355         else
6356             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;
6357         target.y += .1;
6358         if (Person::players[0]->skeleton.free) {
6359             for (int i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
6360                 if (Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y > target.y)
6361                     target.y = Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y;
6362             }
6363             target.y += .1;
6364         }
6365         if (Person::players[0]->skeleton.free != 2) {
6366             cameraspeed = 20;
6367             if (findLengthfast(&Person::players[0]->velocity) > 400) {
6368                 cameraspeed = 20 + (findLength(&Person::players[0]->velocity) - 20) * .96;
6369             }
6370             if (Person::players[0]->skeleton.free == 0 && Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim)
6371                 target.y += 1.4;
6372             coltarget = target - cameraloc;
6373             if (findLengthfast(&coltarget) < multiplier * multiplier * 400)
6374                 cameraloc = target;
6375             else {
6376                 Normalise(&coltarget);
6377                 if (Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim && Person::players[0]->animCurrent != climbanim && Person::players[0]->currentoffset.x == 0)
6378                     cameraloc = cameraloc + coltarget * multiplier * cameraspeed;
6379                 else
6380                     cameraloc = cameraloc + coltarget * multiplier * 8;
6381             }
6382             if (editorenabled)
6383                 cameraloc = target;
6384             cameradist += multiplier * 5;
6385             if (cameradist > 2.3)
6386                 cameradist = 2.3;
6387             viewer = cameraloc - facing * cameradist;
6388             colviewer = viewer;
6389             coltarget = cameraloc;
6390             objects.SphereCheckPossible(&colviewer, findDistance(&colviewer, &coltarget));
6391             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
6392                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
6393                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
6394                     colviewer = viewer;
6395                     coltarget = cameraloc;
6396                     if (objects.model[i].LineCheckPossible(&colviewer, &coltarget, &col, &objects.position[i], &objects.yaw[i]) != -1)
6397                         viewer = col;
6398                 }
6399             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
6400                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
6401                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
6402                     colviewer = viewer;
6403                     if (objects.model[i].SphereCheck(&colviewer, .15, &col, &objects.position[i], &objects.yaw[i]) != -1) {
6404                         viewer = colviewer;
6405                     }
6406                 }
6407             cameradist = findDistance(&viewer, &target);
6408             viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .6);
6409             if (cameraloc.y < terrain.getHeight(cameraloc.x, cameraloc.z)) {
6410                 cameraloc.y = terrain.getHeight(cameraloc.x, cameraloc.z);
6411             }
6412         }
6413         if (camerashake > .8)
6414             camerashake = .8;
6415         woozy += multiplier;
6416         if (Person::players[0]->dead)
6417             camerashake = 0;
6418         if (Person::players[0]->dead)
6419             woozy = 0;
6420         camerashake -= multiplier * 2;
6421         blackout -= multiplier * 2;
6422         if (camerashake < 0)
6423             camerashake = 0;
6424         if (blackout < 0)
6425             blackout = 0;
6426         if (camerashake) {
6427             viewer.x += (float)(Random() % 100) * .0005 * camerashake;
6428             viewer.y += (float)(Random() % 100) * .0005 * camerashake;
6429             viewer.z += (float)(Random() % 100) * .0005 * camerashake;
6430         }
6431     }
6432 }
6433