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