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