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