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