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