]> git.jsancho.org Git - lugaru.git/blob - Source/GameTick.cpp
Fixed methods signatures to fix build
[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 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 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 float pitchTo(XYZ start, XYZ end)
197 {
198     return pitchOf(end - start);
199 }
200 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 void Setenvironment(int which)
373 {
374     LOGFUNC;
375
376     LOG(" Setting environment...");
377
378     float temptexdetail;
379     environment = which;
380
381     pause_sound(stream_snowtheme);
382     pause_sound(stream_grasstheme);
383     pause_sound(stream_deserttheme);
384     pause_sound(stream_wind);
385     pause_sound(stream_desertambient);
386
387
388     if (environment == snowyenvironment) {
389         windvector = 0;
390         windvector.z = 3;
391         if (ambientsound)
392             emit_stream_np(stream_wind);
393
394         Object::treetextureptr.load("Textures/SnowTree.png", 0);
395         Object::bushtextureptr.load("Textures/BushSnow.png", 0);
396         Object::rocktextureptr.load("Textures/BoulderSnow.jpg", 1);
397         Object::boxtextureptr.load("Textures/SnowBox.jpg", 1);
398
399         footstepsound = footstepsn1;
400         footstepsound2 = footstepsn2;
401         footstepsound3 = footstepst1;
402         footstepsound4 = footstepst2;
403
404         terraintexture.load("Textures/Snow.jpg", 1);
405         terraintexture2.load("Textures/Rock.jpg", 1);
406
407
408         temptexdetail = texdetail;
409         if (texdetail > 1)
410             texdetail = 4;
411         skybox->load(   "Textures/Skybox(snow)/Front.jpg",
412                         "Textures/Skybox(snow)/Left.jpg",
413                         "Textures/Skybox(snow)/Back.jpg",
414                         "Textures/Skybox(snow)/Right.jpg",
415                         "Textures/Skybox(snow)/Up.jpg",
416                         "Textures/Skybox(snow)/Down.jpg");
417
418
419
420
421         texdetail = temptexdetail;
422     } else if (environment == desertenvironment) {
423         windvector = 0;
424         windvector.z = 2;
425         Object::treetextureptr.load("Textures/DesertTree.png", 0);
426         Object::bushtextureptr.load("Textures/BushDesert.png", 0);
427         Object::rocktextureptr.load("Textures/BoulderDesert.jpg", 1);
428         Object::boxtextureptr.load("Textures/DesertBox.jpg", 1);
429
430
431         if (ambientsound)
432             emit_stream_np(stream_desertambient);
433
434         footstepsound = footstepsn1;
435         footstepsound2 = footstepsn2;
436         footstepsound3 = footstepsn1;
437         footstepsound4 = footstepsn2;
438
439         terraintexture.load("Textures/Sand.jpg", 1);
440         terraintexture2.load("Textures/SandSlope.jpg", 1);
441
442
443         temptexdetail = texdetail;
444         if (texdetail > 1)
445             texdetail = 4;
446         skybox->load(   "Textures/Skybox(sand)/Front.jpg",
447                         "Textures/Skybox(sand)/Left.jpg",
448                         "Textures/Skybox(sand)/Back.jpg",
449                         "Textures/Skybox(sand)/Right.jpg",
450                         "Textures/Skybox(sand)/Up.jpg",
451                         "Textures/Skybox(sand)/Down.jpg");
452
453
454
455
456         texdetail = temptexdetail;
457     } else if (environment == grassyenvironment) {
458         windvector = 0;
459         windvector.z = 2;
460         Object::treetextureptr.load("Textures/Tree.png", 0);
461         Object::bushtextureptr.load("Textures/Bush.png", 0);
462         Object::rocktextureptr.load("Textures/Boulder.jpg", 1);
463         Object::boxtextureptr.load("Textures/GrassBox.jpg", 1);
464
465         if (ambientsound)
466             emit_stream_np(stream_wind, 100.);
467
468         footstepsound = footstepgr1;
469         footstepsound2 = footstepgr2;
470         footstepsound3 = footstepst1;
471         footstepsound4 = footstepst2;
472
473         terraintexture.load("Textures/GrassDirt.jpg", 1);
474         terraintexture2.load("Textures/MossRock.jpg", 1);
475
476
477         temptexdetail = texdetail;
478         if (texdetail > 1)
479             texdetail = 4;
480         skybox->load(   "Textures/Skybox(grass)/Front.jpg",
481                         "Textures/Skybox(grass)/Left.jpg",
482                         "Textures/Skybox(grass)/Back.jpg",
483                         "Textures/Skybox(grass)/Right.jpg",
484                         "Textures/Skybox(grass)/Up.jpg",
485                         "Textures/Skybox(grass)/Down.jpg");
486
487
488
489         texdetail = temptexdetail;
490     }
491     temptexdetail = texdetail;
492     texdetail = 1;
493     terrain.load("Textures/HeightMap.png");
494
495     texdetail = temptexdetail;
496 }
497
498 void Game::Loadlevel(int which)
499 {
500     stealthloading = 0;
501     whichlevel = which;
502
503     if (which == -1) {
504         Loadlevel("tutorial", true);
505     } else if (which >= 0 && which <= 15) {
506         char buf[32];
507         snprintf(buf, 32, "map%d", which + 1); // challenges
508         Loadlevel(buf);
509     } else
510         Loadlevel("mapsave");
511 }
512
513 void Game::Loadlevel(const std::string& name, bool tutorial)
514 {
515     int indemo; // FIXME this should be removed
516     int templength;
517     float lamefloat;
518
519     LOGFUNC;
520
521     LOG(std::string("Loading level...") + name);
522
523     if (!gameon)
524         visibleloading = true;
525     if (stealthloading)
526         visibleloading = false;
527     if (!stillloading)
528         loadtime = 0;
529     gamestarted = 1;
530
531     numenvsounds = 0;
532
533     Tutorial::active = tutorial;
534
535     if (Tutorial::active) {
536         Tutorial::stage = 0;
537     }
538     if (Tutorial::stage == 0) {
539         Tutorial::stagetime = 0;
540         Tutorial::maxtime = 1;
541     }
542     pause_sound(whooshsound);
543     pause_sound(stream_firesound);
544
545     int mapvers;
546     FILE *tfile;
547     errno = 0;
548     tfile = Folders::openMandatoryFile( Folders::getResourcePath("Maps/"+name), "rb" );
549
550     pause_sound(stream_firesound);
551     scoreadded = 0;
552     windialogue = false;
553     hostiletime = 0;
554     won = 0;
555
556     //~ Animation::animations[bounceidleanim].Load("Idle", middleheight, neutral);
557
558     Dialog::dialogs.clear();
559
560     Dialog::indialogue = -1;
561     cameramode = 0;
562
563     damagedealt = 0;
564     damagetaken = 0;
565
566     if (Account::hasActive()) {
567         difficulty = Account::active().getDifficulty();
568     }
569
570     Hotspot::hotspots.clear();
571     Hotspot::current = -1;
572     bonustime = 1;
573
574     skyboxtexture = 1;
575     skyboxr = 1;
576     skyboxg = 1;
577     skyboxb = 1;
578
579     freeze = 0;
580     winfreeze = 0;
581
582     for (int i = 0; i < 100; i++)
583         bonusnum[i] = 0;
584
585     numfalls = 0;
586     numflipfail = 0;
587     numseen = 0;
588     numstaffattack = 0;
589     numswordattack = 0;
590     numknifeattack = 0;
591     numunarmedattack = 0;
592     numescaped = 0;
593     numflipped = 0;
594     numwallflipped = 0;
595     numthrowkill = 0;
596     numafterkill = 0;
597     numreversals = 0;
598     numattacks = 0;
599     maxalarmed = 0;
600     numresponded = 0;
601
602     bonustotal = startbonustotal;
603     bonus = 0;
604     gameon = 1;
605     changedelay = 0;
606     if (console) {
607         emit_sound_np(consolesuccesssound);
608         freeze = 0;
609         console = false;
610     }
611
612     if (!stealthloading) {
613         terrain.numdecals = 0;
614         Sprite::deleteSprites();
615
616         for (int i = 0; i < subdivision; i++) {
617             for (int j = 0; j < subdivision; j++) {
618                 terrain.patchobjectnum[i][j] = 0;
619             }
620         }
621         Game::LoadingScreen();
622     }
623
624     weapons.clear();
625     Person::players.resize(1);
626
627     funpackf(tfile, "Bi", &mapvers);
628     if (mapvers < 12) {
629         cerr << name << " has obsolete map version " << mapvers << endl;
630     }
631     if (mapvers >= 15)
632         funpackf(tfile, "Bi", &indemo);
633     else
634         indemo = 0;
635     if (mapvers >= 5)
636         funpackf(tfile, "Bi", &maptype);
637     else
638         maptype = mapkilleveryone;
639     if (mapvers >= 6)
640         funpackf(tfile, "Bi", &hostile);
641     else
642         hostile = 1;
643     if (mapvers >= 4)
644         funpackf(tfile, "Bf Bf", &viewdistance, &fadestart);
645     else {
646         viewdistance = 100;
647         fadestart = .6;
648     }
649     if (mapvers >= 2)
650         funpackf(tfile, "Bb Bf Bf Bf", &skyboxtexture, &skyboxr, &skyboxg, &skyboxb);
651     else {
652         skyboxtexture = 1;
653         skyboxr = 1;
654         skyboxg = 1;
655         skyboxb = 1;
656     }
657     if (mapvers >= 10)
658         funpackf(tfile, "Bf Bf Bf", &skyboxlightr, &skyboxlightg, &skyboxlightb);
659     else {
660         skyboxlightr = skyboxr;
661         skyboxlightg = skyboxg;
662         skyboxlightb = skyboxb;
663     }
664     /* 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) */
665     if (stealthloading) {
666         funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat, &lamefloat, &lamefloat, &lamefloat, &lamefloat, &Person::players[0]->num_weapons);
667     } else {
668         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);
669     }
670     if (Person::players[0]->num_weapons > 0 && Person::players[0]->num_weapons < 5)
671         for (int j = 0; j < Person::players[0]->num_weapons; j++) {
672             Person::players[0]->weaponids[j] = weapons.size();
673             int type;
674             funpackf(tfile, "Bi", &type);
675             weapons.push_back(Weapon(type, 0));
676         }
677
678     Game::LoadingScreen();
679
680     funpackf(tfile, "Bf Bf Bf", &Person::players[0]->armorhead, &Person::players[0]->armorhigh, &Person::players[0]->armorlow);
681     funpackf(tfile, "Bf Bf Bf", &Person::players[0]->protectionhead, &Person::players[0]->protectionhigh, &Person::players[0]->protectionlow);
682     funpackf(tfile, "Bf Bf Bf", &Person::players[0]->metalhead, &Person::players[0]->metalhigh, &Person::players[0]->metallow);
683     funpackf(tfile, "Bf Bf", &Person::players[0]->power, &Person::players[0]->speedmult);
684
685     funpackf(tfile, "Bi", &Person::players[0]->numclothes);
686
687     if (mapvers >= 9)
688         funpackf(tfile, "Bi Bi", &Person::players[0]->whichskin, &Person::players[0]->creature);
689     else {
690         Person::players[0]->whichskin = 0;
691         Person::players[0]->creature = rabbittype;
692     }
693
694     Person::players[0]->lastattack = -1;
695     Person::players[0]->lastattack2 = -1;
696     Person::players[0]->lastattack3 = -1;
697
698     //dialogues
699     if (mapvers >= 8) {
700         Dialog::loadDialogs(tfile);
701     }
702
703     for (int k = 0; k < Person::players[0]->numclothes; k++) {
704         funpackf(tfile, "Bi", &templength);
705         for (int l = 0; l < templength; l++)
706             funpackf(tfile, "Bb", &Person::players[0]->clothes[k][l]);
707         Person::players[0]->clothes[k][templength] = '\0';
708         funpackf(tfile, "Bf Bf Bf", &Person::players[0]->clothestintr[k], &Person::players[0]->clothestintg[k], &Person::players[0]->clothestintb[k]);
709     }
710
711     funpackf(tfile, "Bi", &environment);
712
713     Object::LoadObjectsFromFile(tfile, stealthloading);
714
715     if (mapvers >= 7) {
716         int numhotspots;
717         funpackf(tfile, "Bi", &numhotspots);
718         if (numhotspots < 0) {
719             cerr << "Map " << name << " have an invalid number of hotspots" << endl;
720             numhotspots = 0;
721         }
722         Hotspot::hotspots.resize(numhotspots);
723         for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
724             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);
725             funpackf(tfile, "Bi", &templength);
726             if (templength)
727                 for (int l = 0; l < templength; l++)
728                     funpackf(tfile, "Bb", &Hotspot::hotspots[i].text[l]);
729             Hotspot::hotspots[i].text[templength] = '\0';
730             if (Hotspot::hotspots[i].type == -111)
731                 indemo = 1;
732         }
733     } else {
734         Hotspot::hotspots.clear();
735     }
736
737     Game::LoadingScreen();
738
739     if (!stealthloading) {
740         Object::ComputeCenter();
741         Object::ComputeRadius();
742     }
743
744     Game::LoadingScreen();
745
746     int numplayers;
747     funpackf(tfile, "Bi", &numplayers);
748     if (numplayers > maxplayers) {
749         cout << "Warning: this level contains more players than allowed" << endl;
750     }
751     unsigned j = 1;
752     for (int i = 1; i < numplayers; i++) {
753         try {
754             Person::players.push_back(shared_ptr<Person>(new Person(tfile, mapvers, j)));
755             j++;
756         } catch (InvalidPersonException e) {
757             cerr << "Invalid Person found in " << name << endl;
758         }
759     }
760     Game::LoadingScreen();
761
762     funpackf(tfile, "Bi", &numpathpoints);
763     if (numpathpoints > 30 || numpathpoints < 0)
764         numpathpoints = 0;
765     for (int j = 0; j < numpathpoints; j++) {
766         funpackf(tfile, "Bf Bf Bf Bi", &pathpoint[j].x, &pathpoint[j].y, &pathpoint[j].z, &numpathpointconnect[j]);
767         for (int k = 0; k < numpathpointconnect[j]; k++) {
768             funpackf(tfile, "Bi", &pathpointconnect[j][k]);
769         }
770     }
771     Game::LoadingScreen();
772
773     funpackf(tfile, "Bf Bf Bf Bf", &mapcenter.x, &mapcenter.y, &mapcenter.z, &mapradius);
774
775     SetUpLighting();
776     if (environment != oldenvironment)
777         Setenvironment(environment);
778     oldenvironment = environment;
779
780     if (!stealthloading) {
781         Object::AddObjectsToTerrain();
782         terrain.DoShadows();
783         Game::LoadingScreen();
784         Object::DoShadows();
785         Game::LoadingScreen();
786     }
787
788     fclose(tfile);
789
790     for (unsigned i = 0; i < Person::players.size(); i++) {
791         Game::LoadingScreen();
792         if (i == 0) {
793             Person::players[i]->burnt = 0;
794             Person::players[i]->bled = 0;
795             Person::players[i]->onfire = 0;
796             Person::players[i]->scale = .2;
797             if (mapvers < 9) {
798                 Person::players[i]->creature = rabbittype;
799             }
800         }
801         Person::players[i]->skeleton.free = 0;
802
803         Person::players[i]->skeletonLoad();
804
805         Person::players[i]->addClothes();
806
807         if (i == 0) {
808             Person::players[i]->animCurrent = bounceidleanim;
809             Person::players[i]->animTarget = bounceidleanim;
810             Person::players[i]->frameCurrent = 0;
811             Person::players[i]->frameTarget = 1;
812             Person::players[i]->target = 0;
813         }
814         Person::players[i]->speed = 1 + (float)(Random() % 100) / 1000;
815         if (difficulty == 0)
816             Person::players[i]->speed -= .2;
817         if (difficulty == 1)
818             Person::players[i]->speed -= .1;
819
820         if (i == 0) {
821             Person::players[i]->velocity = 0;
822             Person::players[i]->oldcoords = Person::players[i]->coords;
823             Person::players[i]->realoldcoords = Person::players[i]->coords;
824
825             Person::players[i]->id = i;
826             Person::players[i]->updatedelay = 0;
827             Person::players[i]->normalsupdatedelay = 0;
828
829             Person::players[i]->proportionhead = 1.2;
830             Person::players[i]->proportionbody = 1.05;
831             Person::players[i]->proportionarms = 1.00;
832             Person::players[i]->proportionlegs = 1.1;
833             Person::players[i]->proportionlegs.y = 1.05;
834             Person::players[i]->headless = 0;
835             Person::players[i]->currentoffset = 0;
836             Person::players[i]->targetoffset = 0;
837             if (Person::players[i]->creature == wolftype) {
838                 Person::players[i]->scale = .23;
839                 Person::players[i]->damagetolerance = 300;
840             } else {
841                 Person::players[i]->damagetolerance = 200;
842             }
843         }
844
845
846         Game::LoadingScreen();
847
848         if (cellophane) {
849             Person::players[i]->proportionhead.z = 0;
850             Person::players[i]->proportionbody.z = 0;
851             Person::players[i]->proportionarms.z = 0;
852             Person::players[i]->proportionlegs.z = 0;
853         }
854
855         Person::players[i]->tempanimation = Animation("Tempanim", lowheight, neutral);
856
857         if (i == 0) {
858             Person::players[i]->headmorphness = 0;
859             Person::players[i]->targetheadmorphness = 1;
860             Person::players[i]->headmorphstart = 0;
861             Person::players[i]->headmorphend = 0;
862
863             Person::players[i]->pausetime = 0;
864
865             Person::players[i]->dead = 0;
866             Person::players[i]->jumppower = 5;
867             Person::players[i]->damage = 0;
868             Person::players[i]->permanentdamage = 0;
869             Person::players[i]->superpermanentdamage = 0;
870
871             Person::players[i]->forwardkeydown = 0;
872             Person::players[i]->leftkeydown = 0;
873             Person::players[i]->backkeydown = 0;
874             Person::players[i]->rightkeydown = 0;
875             Person::players[i]->jumpkeydown = 0;
876             Person::players[i]->crouchkeydown = 0;
877             Person::players[i]->throwkeydown = 0;
878
879             Person::players[i]->collided = -10;
880             Person::players[i]->loaded = 1;
881             Person::players[i]->bloodloss = 0;
882             Person::players[i]->weaponactive = -1;
883             Person::players[i]->weaponstuck = -1;
884             Person::players[i]->bleeding = 0;
885             Person::players[i]->deathbleeding = 0;
886             Person::players[i]->stunned = 0;
887             Person::players[i]->hasvictim = 0;
888             Person::players[i]->wentforweapon = 0;
889         }
890     }
891
892     Person::players[0]->aitype = playercontrolled;
893
894     if (difficulty == 1) {
895         Person::players[0]->power = 1 / .9;
896         Person::players[0]->damagetolerance = 250;
897     } else if (difficulty == 0) {
898         Person::players[0]->power = 1 / .8;
899         Person::players[0]->damagetolerance = 300;
900         Person::players[0]->armorhead *= 1.5;
901         Person::players[0]->armorhigh *= 1.5;
902         Person::players[0]->armorlow *= 1.5;
903     }
904
905     cameraloc = Person::players[0]->coords;
906     cameraloc.y += 5;
907     yaw = Person::players[0]->yaw;
908
909     hawkcoords = Person::players[0]->coords;
910     hawkcoords.y += 30;
911
912     Game::LoadingScreen();
913
914     LOG("Starting background music...");
915
916     OPENAL_StopSound(OPENAL_ALL);
917     if (ambientsound) {
918         if (environment == snowyenvironment) {
919             emit_stream_np(stream_wind);
920         } else if (environment == desertenvironment) {
921             emit_stream_np(stream_desertambient);
922         } else if (environment == grassyenvironment) {
923             emit_stream_np(stream_wind, 100.);
924         }
925     }
926     oldmusicvolume[0] = 0;
927     oldmusicvolume[1] = 0;
928     oldmusicvolume[2] = 0;
929     oldmusicvolume[3] = 0;
930
931     if (!firstload)
932         firstload = 1;
933
934     leveltime = 0;
935     wonleveltime = 0;
936     visibleloading = false;
937 }
938
939 void doDevKeys()
940 {
941     float headprop, bodyprop, armprop, legprop;
942     if (!devtools) {
943         return;
944     }
945
946     if (Input::isKeyDown(SDL_SCANCODE_LALT)) {
947         /* Invicible */
948         if (Input::isKeyPressed(SDL_SCANCODE_H)) {
949             Person::players[0]->damagetolerance = 200000;
950             Person::players[0]->damage = 0;
951             Person::players[0]->burnt = 0;
952             Person::players[0]->permanentdamage = 0;
953             Person::players[0]->superpermanentdamage = 0;
954         }
955
956         /* Change environment */
957         if (Input::isKeyPressed(SDL_SCANCODE_J)) {
958             environment++;
959             if (environment > 2)
960                 environment = 0;
961             Setenvironment(environment);
962         }
963
964         /* Camera mode */
965         if (Input::isKeyPressed(SDL_SCANCODE_C)) {
966             cameramode = !cameramode;
967         }
968
969         /* Toggle Slow motion */
970         if (Input::isKeyPressed(SDL_SCANCODE_B)) {
971             slomo = 1 - slomo;
972             slomodelay = 1000;
973         }
974
975         /* Ragdoll */
976         if (Input::isKeyPressed(SDL_SCANCODE_N)) {
977             Person::players[0]->RagDoll(0);
978
979             emit_sound_at(whooshsound, Person::players[0]->coords, 128.);
980         }
981
982         /* Grow tree leaves?? */
983         if (Input::isKeyPressed(SDL_SCANCODE_Y)) {
984             for (int i = 0; i < Object::objects.size(); i++) {
985                 if (Object::objects[i]->type == treeleavestype) {
986                     Object::objects[i]->scale *= .9;
987                 }
988             }
989         }
990
991         /* Change (or add) weapon */
992         if (Input::isKeyPressed(SDL_SCANCODE_X)) {
993             int closest = 0;
994             if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
995                 closest = findClosestPlayer();
996             }
997
998             if (closest >= 0) {
999                 if (Person::players[closest]->num_weapons > 0) {
1000                     if (weapons[Person::players[closest]->weaponids[0]].getType() == sword)
1001                         weapons[Person::players[closest]->weaponids[0]].setType(staff);
1002                     else if (weapons[Person::players[closest]->weaponids[0]].getType() == staff)
1003                         weapons[Person::players[closest]->weaponids[0]].setType(knife);
1004                     else
1005                         weapons[Person::players[closest]->weaponids[0]].setType(sword);
1006                 } else {
1007                     Person::players[closest]->weaponids[0] = weapons.size();
1008
1009                     weapons.push_back(Weapon(knife, closest));
1010
1011                     Person::players[closest]->num_weapons = 1;
1012                 }
1013             }
1014         }
1015
1016         /* Change yaw? */
1017         if (Input::isKeyDown(SDL_SCANCODE_U)) {
1018             int closest = 0;
1019             if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1020                 closest = findClosestPlayer();
1021             }
1022
1023             if (closest >= 0) {
1024                 Person::players[closest]->yaw += multiplier * 50;
1025                 Person::players[closest]->targetyaw = Person::players[closest]->yaw;
1026             }
1027         }
1028
1029         /* Toggle fire */
1030         if (Input::isKeyPressed(SDL_SCANCODE_F)) {
1031             Person::players[0]->onfire = 1 - Person::players[0]->onfire;
1032             if (Person::players[0]->onfire) {
1033                 Person::players[0]->CatchFire();
1034             }
1035             if (!Person::players[0]->onfire) {
1036                 emit_sound_at(fireendsound, Person::players[0]->coords);
1037                 pause_sound(stream_firesound);
1038             }
1039         }
1040
1041         /* Change skin */
1042         if (Input::isKeyPressed(SDL_SCANCODE_O) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1043             int closest = 0;
1044             if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1045                 closest = findClosestPlayer();
1046             }
1047
1048             if (closest >= 0) {
1049                 Person::players[closest]->whichskin++;
1050                 if (Person::players[closest]->whichskin > 9)
1051                     Person::players[closest]->whichskin = 0;
1052                 if (Person::players[closest]->whichskin > 2 && Person::players[closest]->creature == wolftype)
1053                     Person::players[closest]->whichskin = 0;
1054
1055                 Person::players[closest]->skeleton.drawmodel.textureptr.load(creatureskin[Person::players[closest]->creature][Person::players[closest]->whichskin], 1,
1056                         &Person::players[closest]->skeleton.skinText[0], &Person::players[closest]->skeleton.skinsize);
1057             }
1058
1059             Person::players[closest]->addClothes();
1060         }
1061
1062         /* Change creature type */
1063         if (Input::isKeyPressed(SDL_SCANCODE_O) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1064             int closest = 0;
1065             if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1066                 closest = findClosestPlayer();
1067             }
1068
1069             if (closest >= 0) {
1070                 if (Person::players[closest]->creature == wolftype) {
1071                     headprop = Person::players[closest]->proportionhead.x / 1.1;
1072                     bodyprop = Person::players[closest]->proportionbody.x / 1.1;
1073                     armprop = Person::players[closest]->proportionarms.x / 1.1;
1074                     legprop = Person::players[closest]->proportionlegs.x / 1.1;
1075                 } else {
1076                     // rabbittype
1077                     headprop = Person::players[closest]->proportionhead.x / 1.2;
1078                     bodyprop = Person::players[closest]->proportionbody.x / 1.05;
1079                     armprop = Person::players[closest]->proportionarms.x / 1.00;
1080                     legprop = Person::players[closest]->proportionlegs.x / 1.1;
1081                 }
1082
1083
1084                 if (Person::players[closest]->creature == rabbittype) {
1085                     Person::players[closest]->creature = wolftype;
1086                     Person::players[closest]->whichskin = 0;
1087                     Person::players[closest]->skeletonLoad();
1088
1089                     Person::players[closest]->proportionhead = 1.1;
1090                     Person::players[closest]->proportionbody = 1.1;
1091                     Person::players[closest]->proportionarms = 1.1;
1092                     Person::players[closest]->proportionlegs = 1.1;
1093                     Person::players[closest]->proportionlegs.y = 1.1;
1094                     Person::players[closest]->scale = .23 * 5 * Person::players[0]->scale;
1095
1096                     Person::players[closest]->damagetolerance = 300;
1097                 } else {
1098                     Person::players[closest]->creature = rabbittype;
1099                     Person::players[closest]->whichskin = 0;
1100                     Person::players[closest]->skeletonLoad(true);
1101
1102                     Person::players[closest]->proportionhead = 1.2;
1103                     Person::players[closest]->proportionbody = 1.05;
1104                     Person::players[closest]->proportionarms = 1.00;
1105                     Person::players[closest]->proportionlegs = 1.1;
1106                     Person::players[closest]->proportionlegs.y = 1.05;
1107                     Person::players[closest]->scale = .2 * 5 * Person::players[0]->scale;
1108
1109                     Person::players[closest]->damagetolerance = 200;
1110                 }
1111
1112                 if (Person::players[closest]->creature == wolftype) {
1113                     Person::players[closest]->proportionhead = 1.1 * headprop;
1114                     Person::players[closest]->proportionbody = 1.1 * bodyprop;
1115                     Person::players[closest]->proportionarms = 1.1 * armprop;
1116                     Person::players[closest]->proportionlegs = 1.1 * legprop;
1117                 }
1118
1119                 if (Person::players[closest]->creature == rabbittype) {
1120                     Person::players[closest]->proportionhead = 1.2 * headprop;
1121                     Person::players[closest]->proportionbody = 1.05 * bodyprop;
1122                     Person::players[closest]->proportionarms = 1.00 * armprop;
1123                     Person::players[closest]->proportionlegs = 1.1 * legprop;
1124                     Person::players[closest]->proportionlegs.y = 1.05 * legprop;
1125                 }
1126
1127             }
1128         }
1129
1130         /* Decapitate */
1131         if (((Input::isKeyPressed(SDL_SCANCODE_I) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
1132             int closest = -1;
1133             float closestdist = std::numeric_limits<float>::max();
1134
1135             for (unsigned i = 1; i < Person::players.size(); i++) {
1136                 float distance = distsq(&Person::players[i]->coords, &Person::players[0]->coords);
1137                 if (!Person::players[i]->headless)
1138                     if (distance < closestdist) {
1139                         closestdist = distance;
1140                         closest = i;
1141                     }
1142             }
1143
1144             XYZ flatfacing2, flatvelocity2;
1145             XYZ blah;
1146             if (closest != -1 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
1147                 blah = Person::players[closest]->coords;
1148                 XYZ headspurtdirection;
1149                 //int i = Person::players[closest]->skeleton.jointlabels[head];
1150                 Joint& headjoint = Person::players[closest]->joint(head);
1151                 for (unsigned k = 0; k < Person::players[closest]->skeleton.joints.size(); k++) {
1152                     if (!Person::players[closest]->skeleton.free)
1153                         flatvelocity2 = Person::players[closest]->velocity;
1154                     if (Person::players[closest]->skeleton.free)
1155                         flatvelocity2 = headjoint.velocity;
1156                     if (!Person::players[closest]->skeleton.free)
1157                         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;
1158                     if (Person::players[closest]->skeleton.free)
1159                         flatfacing2 = headjoint.position * Person::players[closest]->scale + Person::players[closest]->coords;
1160                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1161                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1162                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1163                     headspurtdirection = headjoint.position - Person::players[closest]->jointPos(neck);
1164                     Normalise(&headspurtdirection);
1165                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, .6, 1);
1166                     flatvelocity2 += headspurtdirection * 8;
1167                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 / 2, 1, 1, 1, .16, 1);
1168                 }
1169                 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1170
1171                 emit_sound_at(splattersound, blah);
1172                 emit_sound_at(breaksound2, blah, 100.);
1173
1174                 if (Person::players[closest]->skeleton.free == 2)
1175                     Person::players[closest]->skeleton.free = 0;
1176                 Person::players[closest]->RagDoll(0);
1177                 Person::players[closest]->dead = 2;
1178                 Person::players[closest]->headless = 1;
1179                 Person::players[closest]->DoBloodBig(3, 165);
1180
1181                 camerashake += .3;
1182             }
1183         }
1184
1185         /* Explode */
1186         if (((Input::isKeyPressed(SDL_SCANCODE_I) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
1187             int closest = findClosestPlayer();
1188             XYZ flatfacing2, flatvelocity2;
1189             XYZ blah;
1190             if (closest >= 0 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
1191                 blah = Person::players[closest]->coords;
1192                 emit_sound_at(splattersound, blah);
1193                 emit_sound_at(breaksound2, blah);
1194
1195                 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1196                     if (!Person::players[closest]->skeleton.free)
1197                         flatvelocity2 = Person::players[closest]->velocity;
1198                     if (Person::players[closest]->skeleton.free)
1199                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1200                     if (!Person::players[closest]->skeleton.free)
1201                         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;
1202                     if (Person::players[closest]->skeleton.free)
1203                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1204                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1205                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1206                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1207                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1208                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .3, 1);
1209                     Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1210                 }
1211
1212                 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1213                     if (!Person::players[closest]->skeleton.free)
1214                         flatvelocity2 = Person::players[closest]->velocity;
1215                     if (Person::players[closest]->skeleton.free)
1216                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1217                     if (!Person::players[closest]->skeleton.free)
1218                         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;
1219                     if (Person::players[closest]->skeleton.free)
1220                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1221                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1222                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1223                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1224                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1225                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1226                 }
1227
1228                 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1229                     if (!Person::players[closest]->skeleton.free)
1230                         flatvelocity2 = Person::players[closest]->velocity;
1231                     if (Person::players[closest]->skeleton.free)
1232                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1233                     if (!Person::players[closest]->skeleton.free)
1234                         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;
1235                     if (Person::players[closest]->skeleton.free)
1236                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1237                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1238                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1239                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1240                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
1241                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
1242                 }
1243
1244                 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1245                     if (!Person::players[closest]->skeleton.free)
1246                         flatvelocity2 = Person::players[closest]->velocity;
1247                     if (Person::players[closest]->skeleton.free)
1248                         flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1249                     if (!Person::players[closest]->skeleton.free)
1250                         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;
1251                     if (Person::players[closest]->skeleton.free)
1252                         flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1253                     flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1254                     flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1255                     flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1256                     Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
1257                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
1258                 }
1259
1260                 XYZ temppos;
1261                 for (unsigned j = 0; j < Person::players.size(); j++) {
1262                     if (int(j) != closest) {
1263                         if (distsq(&Person::players[j]->coords, &Person::players[closest]->coords) < 25) {
1264                             Person::players[j]->DoDamage((25 - distsq(&Person::players[j]->coords, &Person::players[closest]->coords)) * 60);
1265                             if (Person::players[j]->skeleton.free == 2)
1266                                 Person::players[j]->skeleton.free = 1;
1267                             Person::players[j]->skeleton.longdead = 0;
1268                             Person::players[j]->RagDoll(0);
1269                             for (unsigned i = 0; i < Person::players[j]->skeleton.joints.size(); i++) {
1270                                 temppos = Person::players[j]->skeleton.joints[i].position + Person::players[j]->coords;
1271                                 if (distsq(&temppos, &Person::players[closest]->coords) < 25) {
1272                                     flatvelocity2 = temppos - Person::players[closest]->coords;
1273                                     Normalise(&flatvelocity2);
1274                                     Person::players[j]->skeleton.joints[i].velocity += flatvelocity2 * ((20 - distsq(&temppos, &Person::players[closest]->coords)) * 20);
1275                                 }
1276                             }
1277                         }
1278                     }
1279                 }
1280
1281                 Person::players[closest]->DoDamage(10000);
1282                 Person::players[closest]->RagDoll(0);
1283                 Person::players[closest]->dead = 2;
1284                 Person::players[closest]->coords = 20;
1285                 Person::players[closest]->skeleton.free = 2;
1286
1287                 camerashake += .6;
1288
1289             }
1290         }
1291
1292         /* Enable editor */
1293         if (Input::isKeyPressed(SDL_SCANCODE_M) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1294             editorenabled = !editorenabled;
1295             if (editorenabled) {
1296                 Person::players[0]->damagetolerance = 100000;
1297             } else {
1298                 Person::players[0]->damagetolerance = 200;
1299             }
1300             Person::players[0]->damage = 0; // these lines were in both if and else, but I think they would better fit in the if
1301             Person::players[0]->permanentdamage = 0;
1302             Person::players[0]->superpermanentdamage = 0;
1303             Person::players[0]->bloodloss = 0;
1304             Person::players[0]->deathbleeding = 0;
1305         }
1306     }
1307
1308     //skip level
1309     if (whichlevel != -2 && Input::isKeyPressed(SDL_SCANCODE_K) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !editorenabled) {
1310         targetlevel++;
1311         if (targetlevel > numchallengelevels - 1)
1312             targetlevel = 0;
1313         loading = 1;
1314         leveltime = 5;
1315     }
1316
1317     if (editorenabled) {
1318         if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1319             int closest = findClosestPlayer();
1320             if (closest >= 0) {
1321                 Person::players.erase(Person::players.begin()+closest);
1322             }
1323         }
1324
1325         if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1326             int closest = findClosestObject();
1327             if (closest >= 0) {
1328                 Object::objects[closest]->position.y -= 500;
1329             }
1330         }
1331
1332         if (Input::isKeyPressed(SDL_SCANCODE_M) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1333             if (Object::objects.size() < max_objects - 1) {
1334                 XYZ scenecoords;
1335                 scenecoords.x = Person::players[0]->coords.x;
1336                 scenecoords.z = Person::players[0]->coords.z;
1337                 scenecoords.y = Person::players[0]->coords.y - 3;
1338                 if (editortype == bushtype)
1339                     scenecoords.y = Person::players[0]->coords.y - .5;
1340                 if (editortype == firetype)
1341                     scenecoords.y = Person::players[0]->coords.y - .5;
1342                 float temprotat, temprotat2;
1343                 temprotat = editoryaw;
1344                 temprotat2 = editorpitch;
1345                 if (temprotat < 0 || editortype == bushtype)
1346                     temprotat = Random() % 360;
1347                 if (temprotat2 < 0)
1348                     temprotat2 = Random() % 360;
1349
1350                 Object::MakeObject(editortype, scenecoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
1351                 if (editortype == treetrunktype)
1352                     Object::MakeObject(treeleavestype, scenecoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
1353             }
1354         }
1355
1356         if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1357             Person::players.push_back(shared_ptr<Person>(new Person()));
1358
1359             Person::players.back()->id = Person::players.size()-1;
1360
1361             Person::players.back()->scale = Person::players[0]->scale;
1362             Person::players.back()->creature = rabbittype;
1363             Person::players.back()->howactive = editoractive;
1364
1365             int k = abs(Random() % 2) + 1;
1366             if (k == 0) {
1367                 Person::players.back()->whichskin = 0;
1368             } else if (k == 1) {
1369                 Person::players.back()->whichskin = 1;
1370             } else {
1371                 Person::players.back()->whichskin = 2;
1372             }
1373
1374             Person::players.back()->skeletonLoad(true);
1375
1376             Person::players.back()->skeleton.drawmodelclothes.textureptr.load("Textures/Belt.png", 1);
1377             Person::players.back()->speed = 1 + (float)(Random() % 100) / 1000;
1378
1379             Person::players.back()->targetyaw = Person::players[0]->targetyaw;
1380             Person::players.back()->yaw = Person::players[0]->yaw;
1381
1382             Person::players.back()->coords = Person::players[0]->coords;
1383             Person::players.back()->oldcoords = Person::players.back()->coords;
1384             Person::players.back()->realoldcoords = Person::players.back()->coords;
1385
1386             if (Person::players[0]->creature == wolftype) {
1387                 headprop = Person::players[0]->proportionhead.x / 1.1;
1388                 bodyprop = Person::players[0]->proportionbody.x / 1.1;
1389                 armprop = Person::players[0]->proportionarms.x / 1.1;
1390                 legprop = Person::players[0]->proportionlegs.x / 1.1;
1391             } else {
1392                 // rabbittype
1393                 headprop = Person::players[0]->proportionhead.x / 1.2;
1394                 bodyprop = Person::players[0]->proportionbody.x / 1.05;
1395                 armprop = Person::players[0]->proportionarms.x / 1.00;
1396                 legprop = Person::players[0]->proportionlegs.x / 1.1;
1397             }
1398
1399             if (Person::players.back()->creature == wolftype) {
1400                 Person::players.back()->proportionhead = 1.1 * headprop;
1401                 Person::players.back()->proportionbody = 1.1 * bodyprop;
1402                 Person::players.back()->proportionarms = 1.1 * armprop;
1403                 Person::players.back()->proportionlegs = 1.1 * legprop;
1404             }
1405
1406             if (Person::players.back()->creature == rabbittype) {
1407                 Person::players.back()->proportionhead = 1.2 * headprop;
1408                 Person::players.back()->proportionbody = 1.05 * bodyprop;
1409                 Person::players.back()->proportionarms = 1.00 * armprop;
1410                 Person::players.back()->proportionlegs = 1.1 * legprop;
1411                 Person::players.back()->proportionlegs.y = 1.05 * legprop;
1412             }
1413
1414             if (cellophane) {
1415                 Person::players.back()->proportionhead.z = 0;
1416                 Person::players.back()->proportionbody.z = 0;
1417                 Person::players.back()->proportionarms.z = 0;
1418                 Person::players.back()->proportionlegs.z = 0;
1419             }
1420
1421             Person::players.back()->tempanimation = Animation("Tempanim", lowheight, neutral);
1422
1423             Person::players.back()->damagetolerance = 200;
1424
1425             Person::players.back()->protectionhead = Person::players[0]->protectionhead;
1426             Person::players.back()->protectionhigh = Person::players[0]->protectionhigh;
1427             Person::players.back()->protectionlow = Person::players[0]->protectionlow;
1428             Person::players.back()->armorhead = Person::players[0]->armorhead;
1429             Person::players.back()->armorhigh = Person::players[0]->armorhigh;
1430             Person::players.back()->armorlow = Person::players[0]->armorlow;
1431             Person::players.back()->metalhead = Person::players[0]->metalhead;
1432             Person::players.back()->metalhigh = Person::players[0]->metalhigh;
1433             Person::players.back()->metallow = Person::players[0]->metallow;
1434
1435             Person::players.back()->immobile = Person::players[0]->immobile;
1436
1437             Person::players.back()->numclothes = Person::players[0]->numclothes;
1438             for (int i = 0; i < Person::players.back()->numclothes; i++) {
1439                 strcpy(Person::players.back()->clothes[i], Person::players[0]->clothes[i]);
1440                 Person::players.back()->clothestintr[i] = Person::players[0]->clothestintr[i];
1441                 Person::players.back()->clothestintg[i] = Person::players[0]->clothestintg[i];
1442                 Person::players.back()->clothestintb[i] = Person::players[0]->clothestintb[i];
1443             }
1444             Person::players.back()->addClothes();
1445
1446             Person::players.back()->power = Person::players[0]->power;
1447             Person::players.back()->speedmult = Person::players[0]->speedmult;
1448
1449             Person::players.back()->loaded = true;
1450         }
1451
1452         if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1453             if (Person::players.back()->numwaypoints < 90) {
1454                 Person::players.back()->waypoints[Person::players.back()->numwaypoints] = Person::players[0]->coords;
1455                 Person::players.back()->waypointtype[Person::players.back()->numwaypoints] = editorpathtype;
1456                 Person::players.back()->numwaypoints++;
1457             }
1458         }
1459
1460         if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1461             if (numpathpoints < 30) {
1462                 bool connected, alreadyconnected;
1463                 connected = 0;
1464                 if (numpathpoints > 1)
1465                     for (int i = 0; i < numpathpoints; i++) {
1466                         if (distsq(&pathpoint[i], &Person::players[0]->coords) < .5 && i != pathpointselected && !connected) {
1467                             alreadyconnected = 0;
1468                             for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
1469                                 if (pathpointconnect[pathpointselected][j] == i)
1470                                     alreadyconnected = 1;
1471                             }
1472                             if (!alreadyconnected) {
1473                                 numpathpointconnect[pathpointselected]++;
1474                                 connected = 1;
1475                                 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
1476                             }
1477                         }
1478                     }
1479                 if (!connected) {
1480                     numpathpoints++;
1481                     pathpoint[numpathpoints - 1] = Person::players[0]->coords;
1482                     numpathpointconnect[numpathpoints - 1] = 0;
1483                     if (numpathpoints > 1 && pathpointselected != -1) {
1484                         numpathpointconnect[pathpointselected]++;
1485                         pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
1486                     }
1487                     pathpointselected = numpathpoints - 1;
1488                 }
1489             }
1490         }
1491
1492         if (Input::isKeyPressed(SDL_SCANCODE_PERIOD)) {
1493             pathpointselected++;
1494             if (pathpointselected >= numpathpoints)
1495                 pathpointselected = -1;
1496         }
1497
1498         if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1499             pathpointselected--;
1500             if (pathpointselected <= -2)
1501                 pathpointselected = numpathpoints - 1;
1502         }
1503
1504         if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1505             if (pathpointselected != -1) {
1506                 numpathpoints--;
1507                 pathpoint[pathpointselected] = pathpoint[numpathpoints];
1508                 numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
1509                 for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
1510                     pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
1511                 }
1512                 for (int i = 0; i < numpathpoints; i++) {
1513                     for (int j = 0; j < numpathpointconnect[i]; j++) {
1514                         if (pathpointconnect[i][j] == pathpointselected) {
1515                             pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
1516                             numpathpointconnect[i]--;
1517                         }
1518                         if (pathpointconnect[i][j] == numpathpoints) {
1519                             pathpointconnect[i][j] = pathpointselected;
1520                         }
1521                     }
1522                 }
1523                 pathpointselected = numpathpoints - 1;
1524             }
1525         }
1526
1527         if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1528             editortype--;
1529             if (editortype == treeleavestype || editortype == 10)
1530                 editortype--;
1531             if (editortype < 0)
1532                 editortype = firetype;
1533         }
1534
1535         if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1536             editortype++;
1537             if (editortype == treeleavestype || editortype == 10)
1538                 editortype++;
1539             if (editortype > firetype)
1540                 editortype = 0;
1541         }
1542
1543         if (Input::isKeyDown(SDL_SCANCODE_LEFT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1544             editoryaw -= multiplier * 100;
1545             if (editoryaw < -.01)
1546                 editoryaw = -.01;
1547         }
1548
1549         if (Input::isKeyDown(SDL_SCANCODE_RIGHT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1550             editoryaw += multiplier * 100;
1551         }
1552
1553         if (Input::isKeyDown(SDL_SCANCODE_UP) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1554             editorsize += multiplier;
1555         }
1556
1557         if (Input::isKeyDown(SDL_SCANCODE_DOWN) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1558             editorsize -= multiplier;
1559             if (editorsize < .1)
1560                 editorsize = .1;
1561         }
1562
1563
1564         if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1565             mapradius -= multiplier * 10;
1566         }
1567
1568         if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1569             mapradius += multiplier * 10;
1570         }
1571
1572         if (Input::isKeyDown(SDL_SCANCODE_UP) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1573             editorpitch += multiplier * 100;
1574         }
1575
1576         if (Input::isKeyDown(SDL_SCANCODE_DOWN) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1577             editorpitch -= multiplier * 100;
1578             if (editorpitch < -.01)
1579                 editorpitch = -.01;
1580         }
1581
1582         if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Object::objects.size() && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1583             int closest = findClosestObject();
1584             if (closest >= 0) {
1585                 Object::DeleteObject(closest);
1586             }
1587         }
1588     }
1589 }
1590
1591 void doJumpReversals()
1592 {
1593     for (unsigned k = 0; k < Person::players.size(); k++)
1594         for (unsigned i = k; i < Person::players.size(); i++) {
1595             if (i == k)
1596                 continue;
1597             if (     Person::players[k]->skeleton.free == 0 &&
1598                      Person::players[i]->skeleton.oldfree == 0 &&
1599                      (Person::players[i]->animTarget == jumpupanim ||
1600                       Person::players[k]->animTarget == jumpupanim) &&
1601                      (Person::players[i]->aitype == playercontrolled ||
1602                       Person::players[k]->aitype == playercontrolled) &&
1603                      ((Person::players[i]->aitype == attacktypecutoff && Person::players[i]->stunned <= 0) ||
1604                       (Person::players[k]->aitype == attacktypecutoff && Person::players[k]->stunned <= 0))) {
1605                 if (     distsq(&Person::players[i]->coords, &Person::players[k]->coords) < 10 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5) &&
1606                          distsqflat(&Person::players[i]->coords, &Person::players[k]->coords) < 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
1607                     //TODO: refactor two huge similar ifs
1608                     if (Person::players[i]->animTarget == jumpupanim &&
1609                             Person::players[k]->animTarget != getupfrombackanim &&
1610                             Person::players[k]->animTarget != getupfromfrontanim &&
1611                             Animation::animations[Person::players[k]->animTarget].height == middleheight &&
1612                             normaldotproduct(Person::players[i]->velocity, Person::players[k]->coords - Person::players[i]->coords) < 0 &&
1613                             ((Person::players[k]->aitype == playercontrolled && Person::players[k]->attackkeydown) ||
1614                              Person::players[k]->aitype != playercontrolled)) {
1615                         Person::players[i]->victim = Person::players[k];
1616                         Person::players[i]->velocity = 0;
1617                         Person::players[i]->animCurrent = jumpreversedanim;
1618                         Person::players[i]->animTarget = jumpreversedanim;
1619                         Person::players[i]->frameCurrent = 0;
1620                         Person::players[i]->frameTarget = 1;
1621                         Person::players[i]->targettilt2 = 0;
1622                         Person::players[k]->victim = Person::players[i];
1623                         Person::players[k]->velocity = 0;
1624                         Person::players[k]->animCurrent = jumpreversalanim;
1625                         Person::players[k]->animTarget = jumpreversalanim;
1626                         Person::players[k]->frameCurrent = 0;
1627                         Person::players[k]->frameTarget = 1;
1628                         Person::players[k]->targettilt2 = 0;
1629                         if (Person::players[i]->coords.y < Person::players[k]->coords.y + 1) {
1630                             Person::players[i]->animCurrent = rabbitkickreversedanim;
1631                             Person::players[i]->animTarget = rabbitkickreversedanim;
1632                             Person::players[i]->frameCurrent = 1;
1633                             Person::players[i]->frameTarget = 2;
1634                             Person::players[k]->animCurrent = rabbitkickreversalanim;
1635                             Person::players[k]->animTarget = rabbitkickreversalanim;
1636                             Person::players[k]->frameCurrent = 1;
1637                             Person::players[k]->frameTarget = 2;
1638                         }
1639                         Person::players[i]->target = 0;
1640                         Person::players[k]->oldcoords = Person::players[k]->coords;
1641                         Person::players[i]->coords = Person::players[k]->coords;
1642                         Person::players[k]->targetyaw = Person::players[i]->targetyaw;
1643                         Person::players[k]->yaw = Person::players[i]->targetyaw;
1644                         if (Person::players[k]->aitype == attacktypecutoff)
1645                             Person::players[k]->stunned = .5;
1646                     }
1647                     if (Person::players[k]->animTarget == jumpupanim &&
1648                             Person::players[i]->animTarget != getupfrombackanim &&
1649                             Person::players[i]->animTarget != getupfromfrontanim &&
1650                             Animation::animations[Person::players[i]->animTarget].height == middleheight &&
1651                             normaldotproduct(Person::players[k]->velocity, Person::players[i]->coords - Person::players[k]->coords) < 0 &&
1652                             ((Person::players[i]->aitype == playercontrolled && Person::players[i]->attackkeydown) ||
1653                              Person::players[i]->aitype != playercontrolled)) {
1654                         Person::players[k]->victim = Person::players[i];
1655                         Person::players[k]->velocity = 0;
1656                         Person::players[k]->animCurrent = jumpreversedanim;
1657                         Person::players[k]->animTarget = jumpreversedanim;
1658                         Person::players[k]->frameCurrent = 0;
1659                         Person::players[k]->frameTarget = 1;
1660                         Person::players[k]->targettilt2 = 0;
1661                         Person::players[i]->victim = Person::players[k];
1662                         Person::players[i]->velocity = 0;
1663                         Person::players[i]->animCurrent = jumpreversalanim;
1664                         Person::players[i]->animTarget = jumpreversalanim;
1665                         Person::players[i]->frameCurrent = 0;
1666                         Person::players[i]->frameTarget = 1;
1667                         Person::players[i]->targettilt2 = 0;
1668                         if (Person::players[k]->coords.y < Person::players[i]->coords.y + 1) {
1669                             Person::players[k]->animTarget = rabbitkickreversedanim;
1670                             Person::players[k]->animCurrent = rabbitkickreversedanim;
1671                             Person::players[i]->animCurrent = rabbitkickreversalanim;
1672                             Person::players[i]->animTarget = rabbitkickreversalanim;
1673                             Person::players[k]->frameCurrent = 1;
1674                             Person::players[k]->frameTarget = 2;
1675                             Person::players[i]->frameCurrent = 1;
1676                             Person::players[i]->frameTarget = 2;
1677                         }
1678                         Person::players[k]->target = 0;
1679                         Person::players[i]->oldcoords = Person::players[i]->coords;
1680                         Person::players[k]->coords = Person::players[i]->coords;
1681                         Person::players[i]->targetyaw = Person::players[k]->targetyaw;
1682                         Person::players[i]->yaw = Person::players[k]->targetyaw;
1683                         if (Person::players[i]->aitype == attacktypecutoff)
1684                             Person::players[i]->stunned = .5;
1685                     }
1686                 }
1687             }
1688         }
1689 }
1690
1691 void doAerialAcrobatics()
1692 {
1693     static XYZ facing, flatfacing;
1694     for (unsigned k = 0; k < Person::players.size(); k++) {
1695         Person::players[k]->turnspeed = 500;
1696
1697         if ((Person::players[k]->isRun() &&
1698                 ((Person::players[k]->targetyaw != rabbitrunninganim &&
1699                   Person::players[k]->targetyaw != wolfrunninganim) ||
1700                  Person::players[k]->frameTarget == 4)) ||
1701                 Person::players[k]->animTarget == removeknifeanim ||
1702                 Person::players[k]->animTarget == crouchremoveknifeanim ||
1703                 Person::players[k]->animTarget == flipanim ||
1704                 Person::players[k]->animTarget == fightsidestep ||
1705                 Person::players[k]->animTarget == walkanim) {
1706             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed);
1707         }
1708
1709
1710         if (Person::players[k]->isStop() ||
1711                 Person::players[k]->isLanding() ||
1712                 Person::players[k]->animTarget == staggerbackhighanim ||
1713                 (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent == sneakanim) ||
1714                 Person::players[k]->animTarget == staggerbackhardanim ||
1715                 Person::players[k]->animTarget == backhandspringanim ||
1716                 Person::players[k]->animTarget == dodgebackanim ||
1717                 Person::players[k]->animTarget == rollanim ||
1718                 (Animation::animations[Person::players[k]->animTarget].attack &&
1719                  Person::players[k]->animTarget != rabbitkickanim &&
1720                  (Person::players[k]->animTarget != crouchstabanim || Person::players[k]->hasvictim) &&
1721                  (Person::players[k]->animTarget != swordgroundstabanim || Person::players[k]->hasvictim))) {
1722             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 2);
1723         }
1724
1725         if (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent != sneakanim) {
1726             Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 4);
1727         }
1728
1729         Person::players[k]->DoStuff();
1730         if (Person::players[k]->immobile && k != 0)
1731             Person::players[k]->coords = Person::players[k]->realoldcoords;
1732
1733         //if player's position has changed (?)
1734         if (distsq(&Person::players[k]->coords, &Person::players[k]->realoldcoords) > 0 &&
1735                 !Person::players[k]->skeleton.free &&
1736                 Person::players[k]->animTarget != climbanim &&
1737                 Person::players[k]->animTarget != hanganim) {
1738             XYZ lowpoint, lowpointtarget, lowpoint2, lowpointtarget2, lowpoint3, lowpointtarget3, lowpoint4, lowpointtarget4, lowpoint5, lowpointtarget5, lowpoint6, lowpointtarget6, lowpoint7, lowpointtarget7, colpoint, colpoint2;
1739             int whichhit;
1740             bool tempcollide = 0;
1741
1742             if (Person::players[k]->collide < -.3)
1743                 Person::players[k]->collide = -.3;
1744             if (Person::players[k]->collide > 1)
1745                 Person::players[k]->collide = 1;
1746             Person::players[k]->collide -= multiplier * 30;
1747
1748             //clip to terrain
1749             Person::players[k]->coords.y = max(Person::players[k]->coords.y, terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z));
1750
1751             for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
1752                 int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
1753                 if (Object::objects[i]->type != rocktype ||
1754                         Object::objects[i]->scale > .5 && Person::players[k]->aitype == playercontrolled ||
1755                         Object::objects[i]->position.y > Person::players[k]->coords.y) {
1756                     lowpoint = Person::players[k]->coords;
1757                     if (Person::players[k]->animTarget != jumpupanim &&
1758                             Person::players[k]->animTarget != jumpdownanim &&
1759                             !Person::players[k]->isFlip())
1760                         lowpoint.y += 1.25;
1761                     else
1762                         lowpoint.y += 1.3;
1763                     if (     Person::players[k]->coords.y < terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) &&
1764                              Person::players[k]->coords.y > terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) - .1)
1765                         Person::players[k]->coords.y = terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z);
1766                     if (Person::players[k]->SphereCheck(&lowpoint, 1.3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1767                         flatfacing = lowpoint - Person::players[k]->coords;
1768                         Person::players[k]->coords = lowpoint;
1769                         Person::players[k]->coords.y -= 1.3;
1770                         Person::players[k]->collide = 1;
1771                         tempcollide = 1;
1772                         //wall jumps
1773                         //TODO: refactor four similar blocks
1774                         if (Person::players[k]->aitype == playercontrolled &&
1775                                 (Person::players[k]->animTarget == jumpupanim ||
1776                                  Person::players[k]->animTarget == jumpdownanim ||
1777                                  Person::players[k]->isFlip()) &&
1778                                 !Person::players[k]->jumptogglekeydown &&
1779                                 Person::players[k]->jumpkeydown) {
1780                             lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, -90, 0) * 1.5;
1781                             XYZ tempcoords1 = lowpoint;
1782                             whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1783                             if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1784                                 Person::players[k]->setAnimation(walljumpleftanim);
1785                                 emit_sound_at(movewhooshsound, Person::players[k]->coords);
1786                                 if (k == 0)
1787                                     pause_sound(whooshsound);
1788
1789                                 lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1790                                 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1791                                 if (lowpointtarget.z < 0)
1792                                     Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1793                                 Person::players[k]->targetyaw = Person::players[k]->yaw;
1794                                 Person::players[k]->lowyaw = Person::players[k]->yaw;
1795                                 if (k == 0)
1796                                     numwallflipped++;
1797                             } else {
1798                                 lowpoint = tempcoords1;
1799                                 lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, 90, 0) * 1.5;
1800                                 whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1801                                 if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1802                                     Person::players[k]->setAnimation(walljumprightanim);
1803                                     emit_sound_at(movewhooshsound, Person::players[k]->coords);
1804                                     if (k == 0)
1805                                         pause_sound(whooshsound);
1806
1807                                     lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1808                                     Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1809                                     if (lowpointtarget.z < 0)
1810                                         Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1811                                     Person::players[k]->targetyaw = Person::players[k]->yaw;
1812                                     Person::players[k]->lowyaw = Person::players[k]->yaw;
1813                                     if (k == 0)
1814                                         numwallflipped++;
1815                                 } else {
1816                                     lowpoint = tempcoords1;
1817                                     lowpointtarget = lowpoint + Person::players[k]->facing * 2;
1818                                     whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1819                                     if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1820                                         Person::players[k]->setAnimation(walljumpbackanim);
1821                                         emit_sound_at(movewhooshsound, Person::players[k]->coords);
1822                                         if (k == 0)
1823                                             pause_sound(whooshsound);
1824
1825                                         lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1826                                         Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1827                                         if (lowpointtarget.z < 0)
1828                                             Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1829                                         Person::players[k]->targetyaw = Person::players[k]->yaw;
1830                                         Person::players[k]->lowyaw = Person::players[k]->yaw;
1831                                         if (k == 0)
1832                                             numwallflipped++;
1833                                     } else {
1834                                         lowpoint = tempcoords1;
1835                                         lowpointtarget = lowpoint - Person::players[k]->facing * 2;
1836                                         whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1837                                         if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1838                                             Person::players[k]->setAnimation(walljumpfrontanim);
1839                                             emit_sound_at(movewhooshsound, Person::players[k]->coords);
1840                                             if (k == 0)
1841                                                 pause_sound(whooshsound);
1842
1843                                             lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1844                                             Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1845                                             if (lowpointtarget.z < 0)
1846                                                 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1847                                             Person::players[k]->yaw += 180;
1848                                             Person::players[k]->targetyaw = Person::players[k]->yaw;
1849                                             Person::players[k]->lowyaw = Person::players[k]->yaw;
1850                                             if (k == 0)
1851                                                 numwallflipped++;
1852                                         }
1853                                     }
1854                                 }
1855                             }
1856                         }
1857                     }
1858                 } else if (Object::objects[i]->type == rocktype) {
1859                     lowpoint2 = Person::players[k]->coords;
1860                     lowpoint = Person::players[k]->coords;
1861                     lowpoint.y += 2;
1862                     if (Object::objects[i]->model.LineCheck(&lowpoint, &lowpoint2, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
1863                         Person::players[k]->coords = colpoint;
1864                         Person::players[k]->collide = 1;
1865                         tempcollide = 1;
1866
1867                         if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) {
1868                             //flipped into a rock
1869                             if (Person::players[k]->isFlip() && Person::players[k]->targetFrame().label == 7)
1870                                 Person::players[k]->RagDoll(0);
1871
1872                             if (Person::players[k]->animTarget == jumpupanim) {
1873                                 Person::players[k]->jumppower = -4;
1874                                 Person::players[k]->animTarget = Person::players[k]->getIdle();
1875                             }
1876                             Person::players[k]->target = 0;
1877                             Person::players[k]->frameTarget = 0;
1878                             Person::players[k]->onterrain = 1;
1879
1880                             if (Person::players[k]->id == 0) {
1881                                 pause_sound(whooshsound);
1882                                 OPENAL_SetVolume(channels[whooshsound], 0);
1883                             }
1884
1885                             //landing
1886                             if ((Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) && !Person::players[k]->wasLanding()) {
1887                                 if (Person::players[k]->isFlip())
1888                                     Person::players[k]->jumppower = -4;
1889                                 Person::players[k]->animTarget = Person::players[k]->getLanding();
1890                                 emit_sound_at(landsound, Person::players[k]->coords, 128.);
1891                                 if (k == 0) {
1892                                     addEnvSound(Person::players[k]->coords);
1893                                 }
1894                             }
1895                         }
1896                     }
1897                 }
1898             }
1899
1900             if (tempcollide)
1901                 for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
1902                     int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
1903                     lowpoint = Person::players[k]->coords;
1904                     lowpoint.y += 1.35;
1905                     if (Object::objects[i]->type != rocktype)
1906                         if (Person::players[k]->SphereCheck(&lowpoint, 1.33, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1907                             if (Person::players[k]->animTarget != jumpupanim &&
1908                                     Person::players[k]->animTarget != jumpdownanim &&
1909                                     Person::players[k]->onterrain)
1910                                 Person::players[k]->avoidcollided = 1;
1911                             Person::players[k]->coords = lowpoint;
1912                             Person::players[k]->coords.y -= 1.35;
1913                             Person::players[k]->collide = 1;
1914
1915                             if ((Person::players[k]->grabdelay <= 0 || Person::players[k]->aitype != playercontrolled) &&
1916                                     (Person::players[k]->animCurrent != climbanim &&
1917                                      Person::players[k]->animCurrent != hanganim &&
1918                                      !Person::players[k]->isWallJump() ||
1919                                      Person::players[k]->animTarget == jumpupanim ||
1920                                      Person::players[k]->animTarget == jumpdownanim)) {
1921                                 lowpoint = Person::players[k]->coords;
1922                                 Object::objects[i]->model.SphereCheckPossible(&lowpoint, 1.5, &Object::objects[i]->position, &Object::objects[i]->yaw);
1923                                 lowpoint = Person::players[k]->coords;
1924                                 lowpoint.y += .05;
1925                                 facing = 0;
1926                                 facing.z = -1;
1927                                 facing = DoRotation(facing, 0, Person::players[k]->targetyaw + 180, 0);
1928                                 lowpointtarget = lowpoint + facing * 1.4;
1929                                 whichhit = Object::objects[i]->model.LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1930                                 if (whichhit != -1) {
1931                                     lowpoint = Person::players[k]->coords;
1932                                     lowpoint.y += .1;
1933                                     lowpointtarget = lowpoint + facing * 1.4;
1934                                     lowpoint2 = lowpoint;
1935                                     lowpointtarget2 = lowpointtarget;
1936                                     lowpoint3 = lowpoint;
1937                                     lowpointtarget3 = lowpointtarget;
1938                                     lowpoint4 = lowpoint;
1939                                     lowpointtarget4 = lowpointtarget;
1940                                     lowpoint5 = lowpoint;
1941                                     lowpointtarget5 = lowpointtarget;
1942                                     lowpoint6 = lowpoint;
1943                                     lowpointtarget6 = lowpointtarget;
1944                                     lowpoint7 = lowpoint;
1945                                     lowpointtarget7 = lowpoint;
1946                                     lowpoint2.x += .1;
1947                                     lowpointtarget2.x += .1;
1948                                     lowpoint3.z += .1;
1949                                     lowpointtarget3.z += .1;
1950                                     lowpoint4.x -= .1;
1951                                     lowpointtarget4.x -= .1;
1952                                     lowpoint5.z -= .1;
1953                                     lowpointtarget5.z -= .1;
1954                                     lowpoint6.y += 45 / 13;
1955                                     lowpointtarget6.y += 45 / 13;
1956                                     lowpointtarget6 += facing * .6;
1957                                     lowpointtarget7.y += 90 / 13;
1958                                     whichhit = Object::objects[i]->model.LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1959                                     if (Object::objects[i]->friction > .5)
1960                                         if (whichhit != -1) {
1961                                             if (whichhit != -1 && Person::players[k]->animTarget != jumpupanim && Person::players[k]->animTarget != jumpdownanim)
1962                                                 Person::players[k]->collided = 1;
1963                                             if (Object::checkcollide(lowpoint7, lowpointtarget7) == -1)
1964                                                 if (Object::checkcollide(lowpoint6, lowpointtarget6) == -1)
1965                                                     if (     Object::objects[i]->model.LineCheckPossible(&lowpoint2, &lowpointtarget2,
1966                                                              &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1 &&
1967                                                              Object::objects[i]->model.LineCheckPossible(&lowpoint3, &lowpointtarget3,
1968                                                                      &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1 &&
1969                                                              Object::objects[i]->model.LineCheckPossible(&lowpoint4, &lowpointtarget4,
1970                                                                      &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1 &&
1971                                                              Object::objects[i]->model.LineCheckPossible(&lowpoint5, &lowpointtarget5,
1972                                                                      &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
1973                                                         for (int j = 0; j < 45; j++) {
1974                                                             lowpoint = Person::players[k]->coords;
1975                                                             lowpoint.y += (float)j / 13;
1976                                                             lowpointtarget = lowpoint + facing * 1.4;
1977                                                             if (Object::objects[i]->model.LineCheckPossible(&lowpoint, &lowpointtarget,
1978                                                                                                    &colpoint2, &Object::objects[i]->position, &Object::objects[i]->yaw) == -1) {
1979                                                                 if (j <= 6 || j <= 25 && Person::players[k]->animTarget == jumpdownanim)
1980                                                                     break;
1981                                                                 if (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim) {
1982                                                                     lowpoint = Person::players[k]->coords;
1983                                                                     lowpoint.y += (float)j / 13;
1984                                                                     lowpointtarget = lowpoint + facing * 1.3;
1985                                                                     flatfacing = Person::players[k]->coords;
1986                                                                     Person::players[k]->coords = colpoint - DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[k]->yaw, 0) * .01;
1987                                                                     Person::players[k]->coords.y = lowpointtarget.y - .07;
1988                                                                     Person::players[k]->currentoffset = (flatfacing - Person::players[k]->coords) / Person::players[k]->scale;
1989
1990                                                                     if (j > 10 || !Person::players[k]->isRun()) {
1991                                                                         if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->animTarget == jumpupanim) {
1992                                                                             if (k == 0)
1993                                                                                 pause_sound(whooshsound);
1994                                                                         }
1995                                                                         emit_sound_at(jumpsound, Person::players[k]->coords, 128.);
1996
1997                                                                         lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1998                                                                         Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1999                                                                         if (lowpointtarget.z < 0)
2000                                                                             Person::players[k]->yaw = 180 - Person::players[k]->yaw;
2001                                                                         Person::players[k]->targetyaw = Person::players[k]->yaw;
2002                                                                         Person::players[k]->lowyaw = Person::players[k]->yaw;
2003
2004                                                                         //Person::players[k]->velocity=lowpointtarget*.03;
2005                                                                         Person::players[k]->velocity = 0;
2006
2007                                                                         //climb ledge (?)
2008                                                                         if (Person::players[k]->animTarget == jumpupanim) {
2009                                                                             Person::players[k]->animTarget = climbanim;
2010                                                                             Person::players[k]->jumppower = 0;
2011                                                                             Person::players[k]->jumpclimb = 1;
2012                                                                         }
2013                                                                         Person::players[k]->transspeed = 6;
2014                                                                         Person::players[k]->target = 0;
2015                                                                         Person::players[k]->frameTarget = 1;
2016                                                                         //hang ledge (?)
2017                                                                         if (j > 25) {
2018                                                                             Person::players[k]->setAnimation(hanganim);
2019                                                                             Person::players[k]->jumppower = 0;
2020                                                                         }
2021                                                                     }
2022                                                                     break;
2023                                                                 }
2024                                                             }
2025                                                         }
2026                                         }
2027                                 }
2028                             }
2029                         }
2030                 }
2031             if (Person::players[k]->collide <= 0) {
2032                 //in the air
2033                 if (!Person::players[k]->onterrain &&
2034                         Person::players[k]->animTarget != jumpupanim &&
2035                         Person::players[k]->animTarget != jumpdownanim &&
2036                         Person::players[k]->animTarget != climbanim &&
2037                         Person::players[k]->animTarget != hanganim &&
2038                         !Person::players[k]->isWallJump() &&
2039                         !Person::players[k]->isFlip()) {
2040                     if (Person::players[k]->animCurrent != climbanim &&
2041                             Person::players[k]->animCurrent != tempanim &&
2042                             Person::players[k]->animTarget != backhandspringanim &&
2043                             (Person::players[k]->animTarget != rollanim ||
2044                              Person::players[k]->frameTarget < 2 ||
2045                              Person::players[k]->frameTarget > 6)) {
2046                         //stagger off ledge (?)
2047                         if (Person::players[k]->animTarget == staggerbackhighanim || Person::players[k]->animTarget == staggerbackhardanim)
2048                             Person::players[k]->RagDoll(0);
2049                         Person::players[k]->setAnimation(jumpdownanim);
2050
2051                         if (!k)
2052                             emit_sound_at(whooshsound, Person::players[k]->coords, 128.);
2053                     }
2054                     //gravity
2055                     Person::players[k]->velocity.y += gravity;
2056                 }
2057             }
2058         }
2059         Person::players[k]->realoldcoords = Person::players[k]->coords;
2060     }
2061 }
2062
2063 void doAttacks()
2064 {
2065     static int randattack;
2066     static bool playerrealattackkeydown = 0;
2067
2068     if (!Input::isKeyDown(attackkey))
2069         oldattackkey = 0;
2070     if (oldattackkey)
2071         Person::players[0]->attackkeydown = 0;
2072     if (oldattackkey)
2073         playerrealattackkeydown = 0;
2074     if (!oldattackkey)
2075         playerrealattackkeydown = Input::isKeyDown(attackkey);
2076     if ((Person::players[0]->parriedrecently <= 0 ||
2077             Person::players[0]->weaponactive == -1) &&
2078             (!oldattackkey ||
2079              (realthreat &&
2080               Person::players[0]->lastattack != swordslashanim &&
2081               Person::players[0]->lastattack != knifeslashstartanim &&
2082               Person::players[0]->lastattack != staffhitanim &&
2083               Person::players[0]->lastattack != staffspinhitanim)))
2084         Person::players[0]->attackkeydown = Input::isKeyDown(attackkey);
2085     if (Input::isKeyDown(attackkey) &&
2086             !oldattackkey &&
2087             !Person::players[0]->backkeydown) {
2088         for (unsigned k = 0; k < Person::players.size(); k++) {
2089             if ((Person::players[k]->animTarget == swordslashanim ||
2090                     Person::players[k]->animTarget == staffhitanim ||
2091                     Person::players[k]->animTarget == staffspinhitanim) &&
2092                     Person::players[0]->animCurrent != dodgebackanim &&
2093                     !Person::players[k]->skeleton.free)
2094                 Person::players[k]->Reverse();
2095         }
2096     }
2097
2098     if (!hostile || Dialog::inDialog())
2099         Person::players[0]->attackkeydown = 0;
2100
2101     for (unsigned k = 0; k < Person::players.size(); k++) {
2102         if (Dialog::inDialog())
2103             Person::players[k]->attackkeydown = 0;
2104         if (Person::players[k]->animTarget != rabbitrunninganim && Person::players[k]->animTarget != wolfrunninganim) {
2105             if (Person::players[k]->aitype != playercontrolled)
2106                 Person::players[k]->victim = Person::players[0];
2107             //attack key pressed
2108             if (Person::players[k]->attackkeydown) {
2109                 //dodge backward
2110                 if (Person::players[k]->backkeydown &&
2111                         Person::players[k]->animTarget != backhandspringanim &&
2112                         (Person::players[k]->isIdle() ||
2113                          Person::players[k]->isStop() ||
2114                          Person::players[k]->isRun() ||
2115                          Person::players[k]->animTarget == walkanim)) {
2116                     if (Person::players[k]->jumppower <= 1) {
2117                         Person::players[k]->jumppower -= 2;
2118                     } else {
2119                         for (unsigned i = 0; i < Person::players.size(); i++) {
2120                             if (i == k)
2121                                 continue;
2122                             if (Person::players[i]->animTarget == swordslashanim ||
2123                                     Person::players[i]->animTarget == knifeslashstartanim ||
2124                                     Person::players[i]->animTarget == staffhitanim ||
2125                                     Person::players[i]->animTarget == staffspinhitanim)
2126                                 if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < 6.5 && !Person::players[i]->skeleton.free) {
2127                                     Person::players[k]->setAnimation(dodgebackanim);
2128                                     Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
2129                                     Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
2130                                 }
2131                         }
2132                         if (Person::players[k]->animTarget != dodgebackanim) {
2133                             if (k == 0)
2134                                 numflipped++;
2135                             Person::players[k]->setAnimation(backhandspringanim);
2136                             Person::players[k]->targetyaw = -yaw + 180;
2137                             if (Person::players[k]->leftkeydown)
2138                                 Person::players[k]->targetyaw -= 45;
2139                             if (Person::players[k]->rightkeydown)
2140                                 Person::players[k]->targetyaw += 45;
2141                             Person::players[k]->yaw = Person::players[k]->targetyaw;
2142                             Person::players[k]->jumppower -= 2;
2143                         }
2144                     }
2145                 }
2146                 //attack
2147                 if (!Animation::animations[Person::players[k]->animTarget].attack &&
2148                         !Person::players[k]->backkeydown &&
2149                         (Person::players[k]->isIdle() ||
2150                          Person::players[k]->isRun() ||
2151                          Person::players[k]->animTarget == walkanim ||
2152                          Person::players[k]->animTarget == sneakanim ||
2153                          Person::players[k]->isCrouch())) {
2154                     const int attackweapon = Person::players[k]->weaponactive == -1 ? 0 : weapons[Person::players[k]->weaponids[Person::players[k]->weaponactive]].getType();
2155                     //normal attacks (?)
2156                     Person::players[k]->hasvictim = 0;
2157                     if (Person::players.size() > 1)
2158                         for (unsigned i = 0; i < Person::players.size(); i++) {
2159                             if (i == k || !(k == 0 || i == 0))
2160                                 continue;
2161                             if (!Person::players[k]->hasvictim)
2162                                 if (Animation::animations[Person::players[k]->animTarget].attack != reversal) {
2163                                     //choose an attack
2164                                     const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
2165                                     if (distance < 4.5 &&
2166                                             !Person::players[i]->skeleton.free &&
2167                                             Person::players[i]->howactive < typedead1 &&
2168                                             Person::players[i]->animTarget != jumpreversedanim &&
2169                                             Person::players[i]->animTarget != rabbitkickreversedanim &&
2170                                             Person::players[i]->animTarget != rabbitkickanim &&
2171                                             Person::players[k]->animTarget != rabbitkickanim &&
2172                                             Person::players[i]->animTarget != getupfrombackanim &&
2173                                             (Person::players[i]->animTarget != staggerbackhighanim &&
2174                                              (Person::players[i]->animTarget != staggerbackhardanim || Person::players[i]->targetFrame().label == 6)) &&
2175                                             Person::players[i]->animTarget != jumpdownanim &&
2176                                             Person::players[i]->animTarget != jumpupanim &&
2177                                             Person::players[i]->animTarget != getupfromfrontanim) {
2178                                         Person::players[k]->victim = Person::players[i];
2179                                         Person::players[k]->hasvictim = 1;
2180                                         if (Person::players[k]->aitype == playercontrolled) { //human player
2181                                             //sweep
2182                                             if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2183                                                     Person::players[k]->crouchkeydown &&
2184                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight)
2185                                                 Person::players[k]->animTarget = sweepanim;
2186                                             //winduppunch
2187                                             else if (distance < 1.5 * sq(Person::players[k]->scale * 5) &&
2188                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2189                                                      !Person::players[k]->forwardkeydown &&
2190                                                      !Person::players[k]->leftkeydown &&
2191                                                      !Person::players[k]->rightkeydown &&
2192                                                      !Person::players[k]->crouchkeydown &&
2193                                                      !attackweapon &&
2194                                                      !reversaltrain)
2195                                                 Person::players[k]->animTarget = winduppunchanim;
2196                                             //upunch
2197                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2198                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2199                                                      !Person::players[k]->forwardkeydown &&
2200                                                      !Person::players[k]->leftkeydown &&
2201                                                      !Person::players[k]->rightkeydown &&
2202                                                      !Person::players[k]->crouchkeydown &&
2203                                                      !attackweapon)
2204                                                 Person::players[k]->animTarget = upunchanim;
2205                                             //knifefollow
2206                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2207                                                      Person::players[i]->staggerdelay > 0 &&
2208                                                      attackweapon == knife &&
2209                                                      Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2)
2210                                                 Person::players[k]->animTarget = knifefollowanim;
2211                                             //knifeslashstart
2212                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2213                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2214                                                      !Person::players[k]->forwardkeydown &&
2215                                                      !Person::players[k]->leftkeydown &&
2216                                                      !Person::players[k]->rightkeydown &&
2217                                                      !Person::players[k]->crouchkeydown &&
2218                                                      attackweapon == knife &&
2219                                                      Person::players[k]->weaponmissdelay <= 0)
2220                                                 Person::players[k]->animTarget = knifeslashstartanim;
2221                                             //swordslash
2222                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2223                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2224                                                      !Person::players[k]->crouchkeydown &&
2225                                                      attackweapon == sword &&
2226                                                      Person::players[k]->weaponmissdelay <= 0)
2227                                                 Person::players[k]->animTarget = swordslashanim;
2228                                             //staffhit
2229                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2230                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2231                                                      !Person::players[k]->crouchkeydown &&
2232                                                      attackweapon == staff &&
2233                                                      Person::players[k]->weaponmissdelay <= 0 &&
2234                                                      !Person::players[k]->leftkeydown &&
2235                                                      !Person::players[k]->rightkeydown &&
2236                                                      !Person::players[k]->forwardkeydown)
2237                                                 Person::players[k]->animTarget = staffhitanim;
2238                                             //staffspinhit
2239                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2240                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2241                                                      !Person::players[k]->crouchkeydown &&
2242                                                      attackweapon == staff &&
2243                                                      Person::players[k]->weaponmissdelay <= 0)
2244                                                 Person::players[k]->animTarget = staffspinhitanim;
2245                                             //spinkick
2246                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2247                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight)
2248                                                 Person::players[k]->animTarget = spinkickanim;
2249                                             //lowkick
2250                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2251                                                      Animation::animations[Person::players[i]->animTarget].height == lowheight &&
2252                                                      Animation::animations[Person::players[k]->animTarget].attack != normalattack)
2253                                                 Person::players[k]->animTarget = lowkickanim;
2254                                         } else { //AI player
2255                                             if (distance < 4.5 * sq(Person::players[k]->scale * 5)) {
2256                                                 randattack = abs(Random() % 5);
2257                                                 if (!attackweapon && distance < 2.5 * sq(Person::players[k]->scale * 5)) {
2258                                                     //sweep
2259                                                     if (randattack == 0 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
2260                                                         Person::players[k]->animTarget = sweepanim;
2261                                                     //upunch
2262                                                     else if (randattack == 1 && Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2263                                                              !attackweapon)
2264                                                         Person::players[k]->animTarget = upunchanim;
2265                                                     //spinkick
2266                                                     else if (randattack == 2 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
2267                                                         Person::players[k]->animTarget = spinkickanim;
2268                                                     //lowkick
2269                                                     else if (Animation::animations[Person::players[i]->animTarget].height == lowheight)
2270                                                         Person::players[k]->animTarget = lowkickanim;
2271                                                 }
2272                                                 if (attackweapon) {
2273                                                     //sweep
2274                                                     if ((!Tutorial::active || !attackweapon) &&
2275                                                             distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2276                                                             randattack == 0 &&
2277                                                             Animation::animations[Person::players[i]->animTarget].height != lowheight)
2278                                                         Person::players[k]->animTarget = sweepanim;
2279                                                     //knifeslashstart
2280                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2281                                                              attackweapon == knife &&
2282                                                              Person::players[k]->weaponmissdelay <= 0)
2283                                                         Person::players[k]->animTarget = knifeslashstartanim;
2284                                                     //swordslash
2285                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
2286                                                                Person::players[0]->hasvictim &&
2287                                                                Person::players[0]->animTarget == swordslashanim) &&
2288                                                              attackweapon == sword &&
2289                                                              Person::players[k]->weaponmissdelay <= 0)
2290                                                         Person::players[k]->animTarget = swordslashanim;
2291                                                     //staffhit
2292                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
2293                                                                Person::players[0]->hasvictim &&
2294                                                                Person::players[0]->animTarget == swordslashanim) &&
2295                                                              attackweapon == staff &&
2296                                                              Person::players[k]->weaponmissdelay <= 0 &&
2297                                                              randattack < 3)
2298                                                         Person::players[k]->animTarget = staffhitanim;
2299                                                     //staffspinhit
2300                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
2301                                                                Person::players[0]->hasvictim &&
2302                                                                Person::players[0]->animTarget == swordslashanim) &&
2303                                                              attackweapon == staff &&
2304                                                              Person::players[k]->weaponmissdelay <= 0 &&
2305                                                              randattack >= 3)
2306                                                         Person::players[k]->animTarget = staffspinhitanim;
2307                                                     //spinkick
2308                                                     else if ((!Tutorial::active || !attackweapon) &&
2309                                                              distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2310                                                              randattack == 1 &&
2311                                                              Animation::animations[Person::players[i]->animTarget].height != lowheight)
2312                                                         Person::players[k]->animTarget = spinkickanim;
2313                                                     //lowkick
2314                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2315                                                              Animation::animations[Person::players[i]->animTarget].height == lowheight &&
2316                                                              Animation::animations[Person::players[k]->animTarget].attack != normalattack)
2317                                                         Person::players[k]->animTarget = lowkickanim;
2318                                                 }
2319                                             }
2320                                         }
2321                                         //upunch becomes wolfslap
2322                                         if (Person::players[k]->animTarget == upunchanim && Person::players[k]->creature == wolftype)
2323                                             Person::players[k]->animTarget = wolfslapanim;
2324                                     }
2325                                     //sneak attacks
2326                                     if ((k == 0) && (!Tutorial::active || Tutorial::stage == 22) &&
2327                                             Person::players[i]->howactive < typedead1 &&
2328                                             distance < 1.5 * sq(Person::players[k]->scale * 5) &&
2329                                             !Person::players[i]->skeleton.free &&
2330                                             Person::players[i]->animTarget != getupfrombackanim &&
2331                                             Person::players[i]->animTarget != getupfromfrontanim &&
2332                                             (Person::players[i]->surprised > 0 ||
2333                                              Person::players[i]->aitype == passivetype ||
2334                                              attackweapon && Person::players[i]->stunned > 0) &&
2335                                             normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[k]->coords) > 0) {
2336                                         //sneakattack
2337                                         if (!attackweapon) {
2338                                             Person::players[k]->animCurrent = sneakattackanim;
2339                                             Person::players[k]->animTarget = sneakattackanim;
2340                                             Person::players[i]->animCurrent = sneakattackedanim;
2341                                             Person::players[i]->animTarget = sneakattackedanim;
2342                                             Person::players[k]->oldcoords = Person::players[k]->coords;
2343                                             Person::players[k]->coords = Person::players[i]->coords;
2344                                         }
2345                                         //knifesneakattack
2346                                         if (attackweapon == knife) {
2347                                             Person::players[k]->animCurrent = knifesneakattackanim;
2348                                             Person::players[k]->animTarget = knifesneakattackanim;
2349                                             Person::players[i]->animCurrent = knifesneakattackedanim;
2350                                             Person::players[i]->animTarget = knifesneakattackedanim;
2351                                             Person::players[i]->oldcoords = Person::players[i]->coords;
2352                                             Person::players[i]->coords = Person::players[k]->coords;
2353                                         }
2354                                         //swordsneakattack
2355                                         if (attackweapon == sword) {
2356                                             Person::players[k]->animCurrent = swordsneakattackanim;
2357                                             Person::players[k]->animTarget = swordsneakattackanim;
2358                                             Person::players[i]->animCurrent = swordsneakattackedanim;
2359                                             Person::players[i]->animTarget = swordsneakattackedanim;
2360                                             Person::players[i]->oldcoords = Person::players[i]->coords;
2361                                             Person::players[i]->coords = Person::players[k]->coords;
2362                                         }
2363                                         if (attackweapon != staff) {
2364                                             Person::players[k]->victim = Person::players[i];
2365                                             Person::players[k]->hasvictim = 1;
2366                                             Person::players[i]->targettilt2 = 0;
2367                                             Person::players[i]->frameTarget = 1;
2368                                             Person::players[i]->frameCurrent = 0;
2369                                             Person::players[i]->target = 0;
2370                                             Person::players[i]->velocity = 0;
2371                                             Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
2372                                             Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
2373                                             Person::players[k]->frameTarget = Person::players[i]->frameTarget;
2374                                             Person::players[k]->target = Person::players[i]->target;
2375                                             Person::players[k]->velocity = 0;
2376                                             Person::players[k]->targetyaw = Person::players[i]->yaw;
2377                                             Person::players[k]->yaw = Person::players[i]->yaw;
2378                                             Person::players[i]->targetyaw = Person::players[i]->yaw;
2379                                         }
2380                                     }
2381                                     if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
2382                                             Person::players[k]->victim == Person::players[i] &&
2383                                             (!Person::players[i]->skeleton.free)) {
2384                                         oldattackkey = 1;
2385                                         Person::players[k]->frameTarget = 0;
2386                                         Person::players[k]->target = 0;
2387
2388                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
2389                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
2390                                         Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
2391                                         Person::players[k]->lastattack2 = Person::players[k]->lastattack;
2392                                         Person::players[k]->lastattack = Person::players[k]->animTarget;
2393                                     }
2394                                     if (Person::players[k]->animTarget == knifefollowanim &&
2395                                             Person::players[k]->victim == Person::players[i]) {
2396                                         oldattackkey = 1;
2397                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
2398                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
2399                                         Person::players[k]->victim = Person::players[i];
2400                                         Person::players[k]->hasvictim = 1;
2401                                         Person::players[i]->animTarget = knifefollowedanim;
2402                                         Person::players[i]->animCurrent = knifefollowedanim;
2403                                         Person::players[i]->targettilt2 = 0;
2404                                         Person::players[i]->targettilt2 = Person::players[k]->targettilt2;
2405                                         Person::players[i]->frameTarget = 1;
2406                                         Person::players[i]->frameCurrent = 0;
2407                                         Person::players[i]->target = 0;
2408                                         Person::players[i]->velocity = 0;
2409                                         Person::players[k]->animCurrent = knifefollowanim;
2410                                         Person::players[k]->animTarget = knifefollowanim;
2411                                         Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
2412                                         Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
2413                                         Person::players[k]->frameTarget = Person::players[i]->frameTarget;
2414                                         Person::players[k]->target = Person::players[i]->target;
2415                                         Person::players[k]->velocity = 0;
2416                                         Person::players[k]->oldcoords = Person::players[k]->coords;
2417                                         Person::players[i]->coords = Person::players[k]->coords;
2418                                         Person::players[i]->targetyaw = Person::players[k]->targetyaw;
2419                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
2420                                         Person::players[k]->yaw = Person::players[k]->targetyaw;
2421                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
2422                                     }
2423                                 }
2424                         }
2425                     const bool hasstaff = attackweapon == staff;
2426                     if (k == 0 && Person::players.size() > 1)
2427                         for (unsigned i = 0; i < Person::players.size(); i++) {
2428                             if (i == k)
2429                                 continue;
2430                             if ((playerrealattackkeydown || Person::players[i]->dead || !hasstaff) &&
2431                                     Animation::animations[Person::players[k]->animTarget].attack == neutral) {
2432                                 const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
2433                                 if (!Person::players[i]->dead || !realthreat || (!attackweapon && Person::players[k]->crouchkeydown))
2434                                     if (Person::players[i]->skeleton.free)
2435                                         if (distance < 3.5 * sq(Person::players[k]->scale * 5) &&
2436                                                 (Person::players[i]->dead ||
2437                                                  Person::players[i]->skeleton.longdead > 1000 ||
2438                                                  Person::players[k]->isRun() ||
2439                                                  hasstaff ||
2440                                                  (attackweapon &&
2441                                                   (Person::players[i]->skeleton.longdead > 2000 ||
2442                                                    Person::players[i]->damage > Person::players[i]->damagetolerance / 8 ||
2443                                                    Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2) &&
2444                                                   distance < 1.5 * sq(Person::players[k]->scale * 5)))) {
2445                                             Person::players[k]->victim = Person::players[i];
2446                                             Person::players[k]->hasvictim = 1;
2447                                             if (attackweapon && !Tutorial::active) {
2448                                                 //crouchstab
2449                                                 if (Person::players[k]->crouchkeydown && attackweapon == knife && distance < 1.5 * sq(Person::players[k]->scale * 5))
2450                                                     Person::players[k]->animTarget = crouchstabanim;
2451                                                 //swordgroundstab
2452                                                 if (Person::players[k]->crouchkeydown && distance < 1.5 * sq(Person::players[k]->scale * 5) && attackweapon == sword)
2453                                                     Person::players[k]->animTarget = swordgroundstabanim;
2454                                                 //staffgroundsmash
2455                                                 if (distance < 3.5 * sq(Person::players[k]->scale * 5) && attackweapon == staff)
2456                                                     Person::players[k]->animTarget = staffgroundsmashanim;
2457                                             }
2458                                             if (distance < 2.5 &&
2459                                                     Person::players[k]->crouchkeydown &&
2460                                                     Person::players[k]->animTarget != crouchstabanim &&
2461                                                     !attackweapon &&
2462                                                     Person::players[i]->dead &&
2463                                                     Person::players[i]->skeleton.free &&
2464                                                     Person::players[i]->skeleton.longdead > 1000) {
2465                                                 Person::players[k]->animTarget = killanim;
2466                                                 //TODO: refactor this out, what does it do?
2467                                                 for (int j = 0; j < terrain.numdecals; j++) {
2468                                                     if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
2469                                                             terrain.decalalivetime[j] < 2)
2470                                                         terrain.DeleteDecal(j);
2471                                                 }
2472                                                 for (int l = 0; l < Object::objects.size(); l++) {
2473                                                     if (Object::objects[l]->model.type == decalstype)
2474                                                         for (int j = 0; j < Object::objects[l]->model.numdecals; j++) {
2475                                                             if ((Object::objects[l]->model.decaltype[j] == blooddecal ||
2476                                                                     Object::objects[l]->model.decaltype[j] == blooddecalslow) &&
2477                                                                     Object::objects[l]->model.decalalivetime[j] < 2)
2478                                                                 Object::objects[l]->model.DeleteDecal(j);
2479                                                         }
2480                                                 }
2481                                             }
2482                                             if (!Person::players[i]->dead || musictype != 2)
2483                                                 if (distance < 3.5 &&
2484                                                         (Person::players[k]->isRun() || Person::players[k]->isIdle() && Person::players[k]->attackkeydown) &&
2485                                                         Person::players[k]->staggerdelay <= 0 &&
2486                                                         (Person::players[i]->dead ||
2487                                                          Person::players[i]->skeleton.longdead < 300 &&
2488                                                          Person::players[k]->lastattack != spinkickanim &&
2489                                                          Person::players[i]->skeleton.free) &&
2490                                                         (!Person::players[i]->dead || musictype != stream_fighttheme)) {
2491                                                     Person::players[k]->animTarget = dropkickanim;
2492                                                     for (int j = 0; j < terrain.numdecals; j++) {
2493                                                         if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
2494                                                                 terrain.decalalivetime[j] < 2) {
2495                                                             terrain.DeleteDecal(j);
2496                                                         }
2497                                                     }
2498                                                     for (int l = 0; l < Object::objects.size(); l++) {
2499                                                         if (Object::objects[l]->model.type == decalstype)
2500                                                             for (int j = 0; j < Object::objects[l]->model.numdecals; j++) {
2501                                                                 if ((Object::objects[l]->model.decaltype[j] == blooddecal ||
2502                                                                         Object::objects[l]->model.decaltype[j] == blooddecalslow) &&
2503                                                                         Object::objects[l]->model.decalalivetime[j] < 2) {
2504                                                                     Object::objects[l]->model.DeleteDecal(j);
2505                                                                 }
2506                                                             }
2507                                                     }
2508                                                 }
2509                                         }
2510                                 if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
2511                                         Person::players[k]->victim == Person::players[i] &&
2512                                         (!Person::players[i]->skeleton.free ||
2513                                          Person::players[k]->animTarget == killanim ||
2514                                          Person::players[k]->animTarget == crouchstabanim ||
2515                                          Person::players[k]->animTarget == swordgroundstabanim ||
2516                                          Person::players[k]->animTarget == staffgroundsmashanim ||
2517                                          Person::players[k]->animTarget == dropkickanim)) {
2518                                     oldattackkey = 1;
2519                                     Person::players[k]->frameTarget = 0;
2520                                     Person::players[k]->target = 0;
2521
2522                                     XYZ targetpoint = Person::players[i]->coords;
2523                                     if (Person::players[k]->animTarget == crouchstabanim ||
2524                                             Person::players[k]->animTarget == swordgroundstabanim ||
2525                                             Person::players[k]->animTarget == staffgroundsmashanim) {
2526                                         targetpoint += (Person::players[i]->jointPos(abdomen) +
2527                                                         Person::players[i]->jointPos(neck)) / 2 *
2528                                                        Person::players[i]->scale;
2529                                     }
2530                                     Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, targetpoint);
2531                                     Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, targetpoint);
2532
2533                                     if (Person::players[k]->animTarget == crouchstabanim || Person::players[k]->animTarget == swordgroundstabanim) {
2534                                         Person::players[k]->targetyaw += (float)(abs(Random() % 100) - 50) / 4;
2535                                     }
2536
2537                                     if (Person::players[k]->animTarget == staffgroundsmashanim)
2538                                         Person::players[k]->targettilt2 += 10;
2539
2540                                     Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
2541                                     Person::players[k]->lastattack2 = Person::players[k]->lastattack;
2542                                     Person::players[k]->lastattack = Person::players[k]->animTarget;
2543
2544                                     if (Person::players[k]->animTarget == swordgroundstabanim) {
2545                                         Person::players[k]->targetyaw += 30;
2546                                     }
2547                                 }
2548                             }
2549                         }
2550                     if (!Person::players[k]->hasvictim) {
2551                         //find victim
2552                         for (unsigned i = 0; i < Person::players.size(); i++) {
2553                             if (i == k || !(i == 0 || k == 0))
2554                                 continue;
2555                             if (!Person::players[i]->skeleton.free) {
2556                                 if (Person::players[k]->hasvictim) {
2557                                     if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) <
2558                                             distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords))
2559                                         Person::players[k]->victim = Person::players[i];
2560                                 } else {
2561                                     Person::players[k]->victim = Person::players[i];
2562                                     Person::players[k]->hasvictim = 1;
2563                                 }
2564                             }
2565                         }
2566                     }
2567                     if (Person::players[k]->aitype == playercontrolled)
2568                         //rabbit kick
2569                         if (Person::players[k]->attackkeydown &&
2570                                 Person::players[k]->isRun() &&
2571                                 Person::players[k]->wasRun() &&
2572                                 ((Person::players[k]->hasvictim &&
2573                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) < 12 * sq(Person::players[k]->scale * 5) &&
2574                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) > 7 * sq(Person::players[k]->scale * 5) &&
2575                                   !Person::players[k]->victim->skeleton.free &&
2576                                   Person::players[k]->victim->animTarget != getupfrombackanim &&
2577                                   Person::players[k]->victim->animTarget != getupfromfrontanim &&
2578                                   Animation::animations[Person::players[k]->victim->animTarget].height != lowheight &&
2579                                   Person::players[k]->aitype != playercontrolled && //wat???
2580                                   normaldotproduct(Person::players[k]->facing, Person::players[k]->victim->coords - Person::players[k]->coords) > 0 &&
2581                                   Person::players[k]->rabbitkickenabled) ||
2582                                  Person::players[k]->jumpkeydown)) {
2583                             oldattackkey = 1;
2584                             Person::players[k]->setAnimation(rabbitkickanim);
2585                         }
2586                     //update counts
2587                     if (Animation::animations[Person::players[k]->animTarget].attack && k == 0) {
2588                         numattacks++;
2589                         switch (attackweapon) {
2590                         case 0:
2591                             numunarmedattack++;
2592                             break;
2593                         case knife:
2594                             numknifeattack++;
2595                             break;
2596                         case sword:
2597                             numswordattack++;
2598                             break;
2599                         case staff:
2600                             numstaffattack++;
2601                             break;
2602                         }
2603                     }
2604                 }
2605             }
2606         }
2607     }
2608 }
2609
2610 void doPlayerCollisions()
2611 {
2612     static XYZ rotatetarget;
2613     static float collisionradius;
2614     if (Person::players.size() > 1)
2615         for (unsigned k = 0; k < Person::players.size(); k++)
2616             for (unsigned i = k + 1; i < Person::players.size(); i++) {
2617                 //neither player is part of a reversal
2618                 if ((Animation::animations[Person::players[i]->animTarget].attack != reversed &&
2619                         Animation::animations[Person::players[i]->animTarget].attack != reversal &&
2620                         Animation::animations[Person::players[k]->animTarget].attack != reversed &&
2621                         Animation::animations[Person::players[k]->animTarget].attack != reversal) || (i != 0 && k != 0))
2622                     if ((Animation::animations[Person::players[i]->animCurrent].attack != reversed &&
2623                             Animation::animations[Person::players[i]->animCurrent].attack != reversal &&
2624                             Animation::animations[Person::players[k]->animCurrent].attack != reversed &&
2625                             Animation::animations[Person::players[k]->animCurrent].attack != reversal) || (i != 0 && k != 0))
2626                         //neither is sleeping
2627                         if (Person::players[i]->howactive <= typesleeping && Person::players[k]->howactive <= typesleeping)
2628                             if (Person::players[i]->howactive != typesittingwall && Person::players[k]->howactive != typesittingwall)
2629                                 //in same patch, neither is climbing
2630                                 if (Person::players[i]->whichpatchx == Person::players[k]->whichpatchx &&
2631                                         Person::players[i]->whichpatchz == Person::players[k]->whichpatchz &&
2632                                         Person::players[k]->skeleton.oldfree == Person::players[k]->skeleton.free &&
2633                                         Person::players[i]->skeleton.oldfree == Person::players[i]->skeleton.free &&
2634                                         Person::players[i]->animTarget != climbanim &&
2635                                         Person::players[i]->animTarget != hanganim &&
2636                                         Person::players[k]->animTarget != climbanim &&
2637                                         Person::players[k]->animTarget != hanganim)
2638                                     //players are close (bounding box test)
2639                                     if (Person::players[i]->coords.y > Person::players[k]->coords.y - 3)
2640                                         if (Person::players[i]->coords.y < Person::players[k]->coords.y + 3)
2641                                             if (Person::players[i]->coords.x > Person::players[k]->coords.x - 3)
2642                                                 if (Person::players[i]->coords.x < Person::players[k]->coords.x + 3)
2643                                                     if (Person::players[i]->coords.z > Person::players[k]->coords.z - 3)
2644                                                         if (Person::players[i]->coords.z < Person::players[k]->coords.z + 3) {
2645                                                             //spread fire from player to player
2646                                                             if (distsq(&Person::players[i]->coords, &Person::players[k]->coords)
2647                                                                     < 3 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
2648                                                                 if (Person::players[i]->onfire || Person::players[k]->onfire) {
2649                                                                     if (!Person::players[i]->onfire)
2650                                                                         Person::players[i]->CatchFire();
2651                                                                     if (!Person::players[k]->onfire)
2652                                                                         Person::players[k]->CatchFire();
2653                                                                 }
2654                                                             }
2655
2656                                                             XYZ tempcoords1 = Person::players[i]->coords;
2657                                                             XYZ tempcoords2 = Person::players[k]->coords;
2658                                                             if (!Person::players[i]->skeleton.oldfree)
2659                                                                 tempcoords1.y += Person::players[i]->jointPos(abdomen).y * Person::players[i]->scale;
2660                                                             if (!Person::players[k]->skeleton.oldfree)
2661                                                                 tempcoords2.y += Person::players[k]->jointPos(abdomen).y * Person::players[k]->scale;
2662                                                             collisionradius = 1.2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
2663                                                             if (Person::players[0]->hasvictim)
2664                                                                 if (Person::players[0]->animTarget == rabbitkickanim && (k == 0 || i == 0) && !Person::players[0]->victim->skeleton.free)
2665                                                                     collisionradius = 3;
2666                                                             if ((!Person::players[i]->skeleton.oldfree || !Person::players[k]->skeleton.oldfree) &&
2667                                                                     (distsq(&tempcoords1, &tempcoords2) < collisionradius ||
2668                                                                      distsq(&Person::players[i]->coords, &Person::players[k]->coords) < collisionradius)) {
2669                                                                 //jump down on a dead body
2670                                                                 if (k == 0 || i == 0) {
2671                                                                     int l = i ? i : k;
2672                                                                     if (Person::players[0]->animTarget == jumpdownanim &&
2673                                                                             !Person::players[0]->skeleton.oldfree &&
2674                                                                             !Person::players[0]->skeleton.free &&
2675                                                                             Person::players[l]->skeleton.oldfree &&
2676                                                                             Person::players[l]->skeleton.free &&
2677                                                                             Person::players[l]->dead &&
2678                                                                             Person::players[0]->lastcollide <= 0 &&
2679                                                                             fabs(Person::players[l]->coords.y - Person::players[0]->coords.y) < .2 &&
2680                                                                             distsq(&Person::players[0]->coords, &Person::players[l]->coords) < .7 * sq((Person::players[l]->scale + Person::players[0]->scale) * 2.5)) {
2681                                                                         Person::players[0]->coords.y = Person::players[l]->coords.y;
2682                                                                         Person::players[l]->velocity = Person::players[0]->velocity;
2683                                                                         Person::players[l]->skeleton.free = 0;
2684                                                                         Person::players[l]->yaw = 0;
2685                                                                         Person::players[l]->RagDoll(0);
2686                                                                         Person::players[l]->DoDamage(20);
2687                                                                         camerashake += .3;
2688                                                                         Person::players[l]->skeleton.longdead = 0;
2689                                                                         Person::players[0]->lastcollide = 1;
2690                                                                     }
2691                                                                 }
2692
2693                                                                 if (     (Person::players[i]->skeleton.oldfree == 1 && findLengthfast(&Person::players[i]->velocity) > 1) ||
2694                                                                          (Person::players[k]->skeleton.oldfree == 1 && findLengthfast(&Person::players[k]->velocity) > 1) ||
2695                                                                          (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0)) {
2696                                                                     rotatetarget = Person::players[k]->velocity - Person::players[i]->velocity;
2697                                                                     if ((Person::players[i]->animTarget != getupfrombackanim && Person::players[i]->animTarget != getupfromfrontanim ||
2698                                                                             Person::players[i]->skeleton.free) &&
2699                                                                             (Person::players[k]->animTarget != getupfrombackanim && Person::players[k]->animTarget != getupfromfrontanim ||
2700                                                                              Person::players[k]->skeleton.free))
2701                                                                         if ((((k != 0 && findLengthfast(&rotatetarget) > 150 ||
2702                                                                                 k == 0 && findLengthfast(&rotatetarget) > 50 && Person::players[0]->rabbitkickragdoll) &&
2703                                                                                 normaldotproduct(rotatetarget, Person::players[k]->coords - Person::players[i]->coords) > 0) &&
2704                                                                                 (k == 0 ||
2705                                                                                  k != 0 && Person::players[i]->skeleton.oldfree == 1 && Animation::animations[Person::players[k]->animCurrent].attack == neutral ||
2706                                                                                  /*i!=0&&*/Person::players[k]->skeleton.oldfree == 1 && Animation::animations[Person::players[i]->animCurrent].attack == neutral)) ||
2707                                                                                 (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) &&
2708                                                                                 (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) &&
2709                                                                                 k == 0 && !Person::players[i]->skeleton.oldfree && !Person::players[k]->skeleton.oldfree) {
2710                                                                             //If hit by body
2711                                                                             if (     (i != 0 || Person::players[i]->skeleton.free) &&
2712                                                                                      (k != 0 || Person::players[k]->skeleton.free) ||
2713                                                                                      (Animation::animations[Person::players[i]->animTarget].height == highheight &&
2714                                                                                       Animation::animations[Person::players[k]->animTarget].height == highheight)) {
2715                                                                                 if (!Tutorial::active) {
2716                                                                                     emit_sound_at(heavyimpactsound, Person::players[i]->coords);
2717                                                                                 }
2718
2719                                                                                 Person::players[i]->RagDoll(0);
2720                                                                                 if (Person::players[i]->damage > Person::players[i]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[i]->dead) {
2721                                                                                     award_bonus(0, aimbonus);
2722                                                                                 }
2723                                                                                 Person::players[i]->DoDamage(findLengthfast(&rotatetarget) / 4);
2724                                                                                 Person::players[k]->RagDoll(0);
2725                                                                                 if (Person::players[k]->damage > Person::players[k]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[k]->dead) {
2726                                                                                     award_bonus(0, aimbonus); // Huh, again?
2727                                                                                 }
2728                                                                                 Person::players[k]->DoDamage(findLengthfast(&rotatetarget) / 4);
2729
2730                                                                                 for (unsigned j = 0; j < Person::players[i]->skeleton.joints.size(); j++) {
2731                                                                                     Person::players[i]->skeleton.joints[j].velocity = Person::players[i]->skeleton.joints[j].velocity / 5 + Person::players[k]->velocity;
2732                                                                                 }
2733                                                                                 for (unsigned j = 0; j < Person::players[k]->skeleton.joints.size(); j++) {
2734                                                                                     Person::players[k]->skeleton.joints[j].velocity = Person::players[k]->skeleton.joints[j].velocity / 5 + Person::players[i]->velocity;
2735                                                                                 }
2736
2737                                                                             }
2738                                                                         }
2739                                                                     if (     (Animation::animations[Person::players[i]->animTarget].attack == neutral ||
2740                                                                               Animation::animations[Person::players[i]->animTarget].attack == normalattack) &&
2741                                                                              (Animation::animations[Person::players[k]->animTarget].attack == neutral ||
2742                                                                               Animation::animations[Person::players[k]->animTarget].attack == normalattack)) {
2743                                                                         //If bumped
2744                                                                         if (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0) {
2745                                                                             if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < .5 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
2746                                                                                 rotatetarget = Person::players[k]->coords - Person::players[i]->coords;
2747                                                                                 Normalise(&rotatetarget);
2748                                                                                 Person::players[k]->coords = (Person::players[k]->coords + Person::players[i]->coords) / 2;
2749                                                                                 Person::players[i]->coords = Person::players[k]->coords - rotatetarget * fast_sqrt(.6) / 2
2750                                                                                                    * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
2751                                                                                 Person::players[k]->coords += rotatetarget * fast_sqrt(.6) / 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
2752                                                                                 if (Person::players[k]->howactive == typeactive || hostile)
2753                                                                                     if (Person::players[k]->isIdle()) {
2754                                                                                         if (Person::players[k]->howactive < typesleeping)
2755                                                                                             Person::players[k]->setAnimation(Person::players[k]->getStop());
2756                                                                                         else if (Person::players[k]->howactive == typesleeping)
2757                                                                                             Person::players[k]->setAnimation(getupfromfrontanim);
2758                                                                                         if (!editorenabled)
2759                                                                                             Person::players[k]->howactive = typeactive;
2760                                                                                     }
2761                                                                                 if (Person::players[i]->howactive == typeactive || hostile)
2762                                                                                     if (Person::players[i]->isIdle()) {
2763                                                                                         if (Person::players[i]->howactive < typesleeping)
2764                                                                                             Person::players[i]->setAnimation(Person::players[k]->getStop());
2765                                                                                         else
2766                                                                                             Person::players[i]->setAnimation(getupfromfrontanim);
2767                                                                                         if (!editorenabled)
2768                                                                                             Person::players[i]->howactive = typeactive;
2769                                                                                     }
2770                                                                             }
2771                                                                             //jump down on player
2772                                                                             if (hostile) {
2773                                                                                 if (k == 0 && i != 0 && Person::players[k]->animTarget == jumpdownanim &&
2774                                                                                         !Person::players[i]->isCrouch() &&
2775                                                                                         Person::players[i]->animTarget != rollanim &&
2776                                                                                         !Person::players[k]->skeleton.oldfree && !
2777                                                                                         Person::players[k]->skeleton.free &&
2778                                                                                         Person::players[k]->lastcollide <= 0 &&
2779                                                                                         Person::players[k]->velocity.y < -10) {
2780                                                                                     Person::players[i]->velocity = Person::players[k]->velocity;
2781                                                                                     Person::players[k]->velocity = Person::players[k]->velocity * -.5;
2782                                                                                     Person::players[k]->velocity.y = Person::players[i]->velocity.y;
2783                                                                                     Person::players[i]->DoDamage(20);
2784                                                                                     Person::players[i]->RagDoll(0);
2785                                                                                     Person::players[k]->lastcollide = 1;
2786                                                                                     award_bonus(k, AboveBonus);
2787                                                                                 }
2788                                                                                 if (i == 0 && k != 0 && Person::players[i]->animTarget == jumpdownanim &&
2789                                                                                         !Person::players[k]->isCrouch() &&
2790                                                                                         Person::players[k]->animTarget != rollanim &&
2791                                                                                         !Person::players[i]->skeleton.oldfree &&
2792                                                                                         !Person::players[i]->skeleton.free &&
2793                                                                                         Person::players[i]->lastcollide <= 0 &&
2794                                                                                         Person::players[i]->velocity.y < -10) {
2795                                                                                     Person::players[k]->velocity = Person::players[i]->velocity;
2796                                                                                     Person::players[i]->velocity = Person::players[i]->velocity * -.3;
2797                                                                                     Person::players[i]->velocity.y = Person::players[k]->velocity.y;
2798                                                                                     Person::players[k]->DoDamage(20);
2799                                                                                     Person::players[k]->RagDoll(0);
2800                                                                                     Person::players[i]->lastcollide = 1;
2801                                                                                     award_bonus(i, AboveBonus);
2802                                                                                 }
2803                                                                             }
2804                                                                         }
2805                                                                     }
2806                                                                 }
2807                                                                 Person::players[i]->CheckKick();
2808                                                                 Person::players[k]->CheckKick();
2809                                                             }
2810                                                         }
2811             }
2812 }
2813
2814 void Game::Tick()
2815 {
2816     static XYZ facing, flatfacing;
2817     static int target;
2818
2819     Input::Tick();
2820
2821     if (Input::isKeyPressed(SDL_SCANCODE_F6)) {
2822         if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
2823             stereoreverse = true;
2824         else
2825             stereoreverse = false;
2826
2827         if (stereoreverse)
2828             printf("Stereo reversed\n");
2829         else
2830             printf("Stereo unreversed\n");
2831     }
2832
2833     if (Input::isKeyDown(SDL_SCANCODE_F7)) {
2834         if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
2835             stereoseparation -= 0.001;
2836         else
2837             stereoseparation -= 0.010;
2838         printf("Stereo decreased increased to %f\n", stereoseparation);
2839     }
2840
2841     if (Input::isKeyDown(SDL_SCANCODE_F8)) {
2842         if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
2843             stereoseparation += 0.001;
2844         else
2845             stereoseparation += 0.010;
2846         printf("Stereo separation increased to %f\n", stereoseparation);
2847     }
2848
2849
2850     if (Input::isKeyPressed(SDL_SCANCODE_TAB) && Tutorial::active) {
2851         if (Tutorial::stage != 51) {
2852             Tutorial::stagetime = Tutorial::maxtime;
2853         }
2854         emit_sound_np(consolefailsound, 128.);
2855     }
2856
2857     /*
2858     Values of mainmenu :
2859     1 Main menu
2860     2 Menu pause (resume/end game)
2861     3 Option menu
2862     4 Controls configuration menu
2863     5 Main game menu (choose level or challenge)
2864     6 Deleting user menu
2865     7 User managment menu (select/add)
2866     8 Choose difficulty menu
2867     9 Challenge level selection menu
2868     10 End of the campaign congratulation (is that really a menu?)
2869     11 Same that 9 ??? => unused
2870     18 stereo configuration
2871     */
2872
2873     if (!console) {
2874         //campaign over?
2875         if (mainmenu && endgame == 1)
2876             mainmenu = 10;
2877         //go to level select after completing a campaign level
2878         if (campaign && winfreeze && mainmenu == 0 && campaignlevels[actuallevel].choosenext == 1) {
2879             mainmenu = 5;
2880             gameon = 0;
2881             winfreeze = 0;
2882             fireSound();
2883             flash();
2884             if (musictoggle) {
2885                 OPENAL_SetFrequency(OPENAL_ALL);
2886                 emit_stream_np(stream_menutheme);
2887                 pause_sound(leveltheme);
2888             }
2889             Menu::Load();
2890         }
2891         //escape key pressed
2892         if (Input::isKeyPressed(SDL_SCANCODE_ESCAPE) &&
2893                 (gameon || mainmenu == 0)) {
2894             selected = -1;
2895             if (mainmenu == 0 && !winfreeze)
2896                 mainmenu = 2; //pause
2897             else if (mainmenu == 1 || mainmenu == 2) {
2898                 mainmenu = 0; //unpause
2899             }
2900             //play menu theme
2901             if (musictoggle && (mainmenu == 1 || mainmenu == 2)) {
2902                 OPENAL_SetFrequency(OPENAL_ALL);
2903                 emit_stream_np(stream_menutheme);
2904                 pause_sound(leveltheme);
2905             }
2906             //on resume, play level music
2907             if (!mainmenu) {
2908                 pause_sound(stream_menutheme);
2909                 resume_stream(leveltheme);
2910             }
2911         }
2912     }
2913
2914     if (mainmenu) {
2915         Menu::Tick();
2916     }
2917
2918     if (!mainmenu) {
2919         if (hostile == 1)
2920             hostiletime += multiplier;
2921         else
2922             hostiletime = 0;
2923         if (!winfreeze)
2924             leveltime += multiplier;
2925
2926         //keys
2927         if (Input::isKeyDown(SDL_SCANCODE_LALT) && Input::isKeyPressed(SDL_SCANCODE_V) && devtools) {
2928             freeze = !freeze;
2929             if (freeze) {
2930                 OPENAL_SetFrequency(OPENAL_ALL);
2931             }
2932         }
2933
2934         if (Input::isKeyPressed(consolekey) && devtools) {
2935             console = !console;
2936             if (console) {
2937                 OPENAL_SetFrequency(OPENAL_ALL);
2938             } else {
2939                 freeze = 0;
2940                 waiting = false;
2941             }
2942         }
2943
2944         if (console)
2945             freeze = 1;
2946         if (console && !Input::isKeyDown(SDL_SCANCODE_LGUI)) {
2947             inputText(consoletext[0], &consoleselected);
2948             if (!waiting) {
2949                 if (!consoletext[0].empty()) {
2950                     cmd_dispatch(consoletext[0]);
2951                     for (int k = 14; k >= 1; k--) {
2952                         consoletext[k] = consoletext[k - 1];
2953                     }
2954                     consoletext[0].clear();
2955                     consoleselected = 0;
2956                 }
2957             }
2958
2959             consoleblinkdelay -= multiplier;
2960             if (consoleblinkdelay <= 0) {
2961                 consoleblinkdelay = .3;
2962                 consoleblink = !consoleblink;
2963             }
2964         }
2965
2966         static int oldwinfreeze;
2967         if (winfreeze && !oldwinfreeze) {
2968             OPENAL_SetFrequency(OPENAL_ALL);
2969             emit_sound_np(consolesuccesssound);
2970         }
2971         if (winfreeze == 0)
2972             oldwinfreeze = winfreeze;
2973         else
2974             oldwinfreeze++;
2975
2976         if ((Input::isKeyPressed(jumpkey) || Input::isKeyPressed(SDL_SCANCODE_SPACE)) && !campaign)
2977             if (winfreeze)
2978                 winfreeze = 0;
2979         if ((Input::isKeyDown(SDL_SCANCODE_ESCAPE)) && !campaign && gameon) {
2980             if (console) {
2981                 console = false;
2982                 freeze = 0;
2983             } else if (winfreeze) {
2984                 mainmenu = 9;
2985                 gameon = 0;
2986             }
2987         }
2988
2989
2990
2991         if (!freeze && !winfreeze && !(mainmenu && gameon) && (gameon || !gamestarted)) {
2992
2993             //dialogues
2994             static float talkdelay = 0;
2995
2996             if (Dialog::inDialog())
2997                 talkdelay = 1;
2998             talkdelay -= multiplier;
2999
3000             if (talkdelay <= 0 && !Dialog::inDialog() && Animation::animations[Person::players[0]->animTarget].height != highheight) {
3001                 for (unsigned i = 0; i < Dialog::dialogs.size(); i++) {
3002                     Dialog::dialogs[i].tick(i);
3003                 }
3004             }
3005
3006             windvar += multiplier;
3007             smoketex += multiplier;
3008             Tutorial::stagetime += multiplier;
3009
3010             //hotspots
3011             static float hotspotvisual[40];
3012             if (Hotspot::hotspots.size()) {
3013                 XYZ hotspotsprite;
3014                 if (editorenabled) {
3015                     for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
3016                         hotspotvisual[i] -= multiplier / 320;
3017                     }
3018                 }
3019
3020                 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
3021                     while (hotspotvisual[i] < 0) {
3022                         hotspotsprite = 0;
3023                         hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * Hotspot::hotspots[i].size;
3024                         hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
3025                         hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
3026                         hotspotsprite += Hotspot::hotspots[i].position;
3027                         Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
3028                         hotspotvisual[i] += 0.1 / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size;
3029                     }
3030                 }
3031
3032                 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
3033                     if (Hotspot::hotspots[i].type <= 10 && Hotspot::hotspots[i].type > 0) {
3034                         Hotspot::hotspots[i].position = Person::players[Hotspot::hotspots[i].type]->coords;
3035                     }
3036                 }
3037             }
3038
3039             //Tutorial
3040             if (Tutorial::active) {
3041                 Tutorial::Do(multiplier);
3042             }
3043
3044             //bonuses
3045             if (!Tutorial::active) {
3046                 if (bonustime == 0 &&
3047                         bonus != solidhit &&
3048                         bonus != spinecrusher &&
3049                         bonus != tracheotomy &&
3050                         bonus != backstab &&
3051                         bonusvalue > 10) {
3052                     emit_sound_np(consolesuccesssound);
3053                 }
3054             } else if (bonustime == 0) {
3055                 emit_sound_np(fireendsound);
3056             }
3057             if (bonustime == 0) {
3058                 if (bonus != solidhit &&
3059                         bonus != twoxcombo &&
3060                         bonus != threexcombo &&
3061                         bonus != fourxcombo &&
3062                         bonus != megacombo)
3063                     bonusnum[bonus]++;
3064                 else
3065                     bonusnum[bonus] += 0.15;
3066                 if (Tutorial::active)
3067                     bonusvalue = 0;
3068                 bonusvalue /= bonusnum[bonus];
3069                 bonustotal += bonusvalue;
3070             }
3071             bonustime += multiplier;
3072
3073             //snow effects
3074             if (environment == snowyenvironment) {
3075                 precipdelay -= multiplier;
3076                 while (precipdelay < 0) {
3077                     precipdelay += .04;
3078                     if (!detail)
3079                         precipdelay += .04;
3080                     XYZ footvel, footpoint;
3081
3082                     footvel = 0;
3083                     footpoint = viewer + viewerfacing * 6;
3084                     footpoint.y += ((float)abs(Random() % 1200)) / 100 - 6;
3085                     footpoint.x += ((float)abs(Random() % 1200)) / 100 - 6;
3086                     footpoint.z += ((float)abs(Random() % 1200)) / 100 - 6;
3087                     Sprite::MakeSprite(snowsprite, footpoint, footvel, 1, 1, 1, .1, 1);
3088                 }
3089             }
3090
3091
3092             doAerialAcrobatics();
3093
3094
3095             static XYZ oldviewer;
3096
3097             //control keys
3098             if (!Dialog::inDialog()) {
3099                 Person::players[0]->forwardkeydown = Input::isKeyDown(forwardkey);
3100                 Person::players[0]->leftkeydown = Input::isKeyDown(leftkey);
3101                 Person::players[0]->backkeydown = Input::isKeyDown(backkey);
3102                 Person::players[0]->rightkeydown = Input::isKeyDown(rightkey);
3103                 Person::players[0]->jumpkeydown = Input::isKeyDown(jumpkey);
3104                 Person::players[0]->crouchkeydown = Input::isKeyDown(crouchkey);
3105                 Person::players[0]->drawkeydown = Input::isKeyDown(drawkey);
3106                 Person::players[0]->throwkeydown = Input::isKeyDown(throwkey);
3107             } else {
3108                 Person::players[0]->forwardkeydown = 0;
3109                 Person::players[0]->leftkeydown = 0;
3110                 Person::players[0]->backkeydown = 0;
3111                 Person::players[0]->rightkeydown = 0;
3112                 Person::players[0]->jumpkeydown = 0;
3113                 Person::players[0]->crouchkeydown = 0;
3114                 Person::players[0]->drawkeydown = 0;
3115                 Person::players[0]->throwkeydown = 0;
3116             }
3117
3118             if (!Person::players[0]->jumpkeydown)
3119                 Person::players[0]->jumpclimb = 0;
3120
3121
3122             if (Dialog::inDialog()) {
3123                 cameramode = 1;
3124                 if (Dialog::directing) {
3125                     facing = 0;
3126                     facing.z = -1;
3127
3128                     facing = DoRotation(facing, -pitch, 0, 0);
3129                     facing = DoRotation(facing, 0, 0 - yaw, 0);
3130
3131                     flatfacing = 0;
3132                     flatfacing.z = -1;
3133
3134                     flatfacing = DoRotation(flatfacing, 0, -yaw, 0);
3135
3136                     if (Input::isKeyDown(forwardkey))
3137                         viewer += facing * multiplier * 4;
3138                     if (Input::isKeyDown(backkey))
3139                         viewer -= facing * multiplier * 4;
3140                     if (Input::isKeyDown(leftkey))
3141                         viewer += DoRotation(flatfacing * multiplier, 0, 90, 0) * 4;
3142                     if (Input::isKeyDown(rightkey))
3143                         viewer += DoRotation(flatfacing * multiplier, 0, -90, 0) * 4;
3144                     if (Input::isKeyDown(jumpkey))
3145                         viewer.y += multiplier * 4;
3146                     if (Input::isKeyDown(crouchkey))
3147                         viewer.y -= multiplier * 4;
3148                     if (     Input::isKeyPressed(SDL_SCANCODE_1) ||
3149                              Input::isKeyPressed(SDL_SCANCODE_2) ||
3150                              Input::isKeyPressed(SDL_SCANCODE_3) ||
3151                              Input::isKeyPressed(SDL_SCANCODE_4) ||
3152                              Input::isKeyPressed(SDL_SCANCODE_5) ||
3153                              Input::isKeyPressed(SDL_SCANCODE_6) ||
3154                              Input::isKeyPressed(SDL_SCANCODE_7) ||
3155                              Input::isKeyPressed(SDL_SCANCODE_8) ||
3156                              Input::isKeyPressed(SDL_SCANCODE_9) ||
3157                              Input::isKeyPressed(SDL_SCANCODE_0) ||
3158                              Input::isKeyPressed(SDL_SCANCODE_MINUS)) {
3159                         int whichend;
3160                         if (Input::isKeyPressed(SDL_SCANCODE_1)) whichend = 1;
3161                         if (Input::isKeyPressed(SDL_SCANCODE_2)) whichend = 2;
3162                         if (Input::isKeyPressed(SDL_SCANCODE_3)) whichend = 3;
3163                         if (Input::isKeyPressed(SDL_SCANCODE_4)) whichend = 4;
3164                         if (Input::isKeyPressed(SDL_SCANCODE_5)) whichend = 5;
3165                         if (Input::isKeyPressed(SDL_SCANCODE_6)) whichend = 6;
3166                         if (Input::isKeyPressed(SDL_SCANCODE_7)) whichend = 7;
3167                         if (Input::isKeyPressed(SDL_SCANCODE_8)) whichend = 8;
3168                         if (Input::isKeyPressed(SDL_SCANCODE_9)) whichend = 9;
3169                         if (Input::isKeyPressed(SDL_SCANCODE_0)) whichend = 0;
3170                         if (Input::isKeyPressed(SDL_SCANCODE_MINUS))
3171                             whichend = -1;
3172                         if (whichend != -1) {
3173                             Dialog::currentScene().participantfocus = whichend;
3174                             Dialog::currentDialog().participantlocation[whichend] = Person::players[whichend]->coords;
3175                             Dialog::currentDialog().participantyaw[whichend] = Person::players[whichend]->yaw;
3176                         }
3177                         if (whichend == -1) {
3178                             Dialog::currentScene().participantfocus = -1;
3179                         }
3180                         /* FIXME: potentially accessing -1 in Person::players! */
3181                         if (Person::players[Dialog::currentScene().participantfocus]->dead) {
3182                             Dialog::indialogue = -1;
3183                             Dialog::directing = false;
3184                             cameramode = 0;
3185                         }
3186                         Dialog::currentScene().camera = viewer;
3187                         Dialog::currentScene().camerayaw = yaw;
3188                         Dialog::currentScene().camerapitch = pitch;
3189                         Dialog::indialogue++;
3190                         if (Dialog::indialogue < int(Dialog::currentDialog().scenes.size())) {
3191                             if (Dialog::currentScene().sound != 0) {
3192                                 playdialoguescenesound();
3193                             }
3194                         }
3195
3196                         for (unsigned j = 0; j < Person::players.size(); j++) {
3197                             Dialog::currentScene().participantfacing[j] = Dialog::currentDialog().scenes[Dialog::indialogue - 1].participantfacing[j];
3198                         }
3199                     }
3200                     //TODO: should these be KeyDown or KeyPressed?
3201                     if (     Input::isKeyDown(SDL_SCANCODE_KP_1) ||
3202                              Input::isKeyDown(SDL_SCANCODE_KP_2) ||
3203                              Input::isKeyDown(SDL_SCANCODE_KP_3) ||
3204                              Input::isKeyDown(SDL_SCANCODE_KP_4) ||
3205                              Input::isKeyDown(SDL_SCANCODE_KP_5) ||
3206                              Input::isKeyDown(SDL_SCANCODE_KP_6) ||
3207                              Input::isKeyDown(SDL_SCANCODE_KP_7) ||
3208                              Input::isKeyDown(SDL_SCANCODE_KP_8) ||
3209                              Input::isKeyDown(SDL_SCANCODE_KP_9) ||
3210                              Input::isKeyDown(SDL_SCANCODE_KP_0)) {
3211                         int whichend;
3212                         if (Input::isKeyDown(SDL_SCANCODE_KP_1)) whichend = 1;
3213                         if (Input::isKeyDown(SDL_SCANCODE_KP_2)) whichend = 2;
3214                         if (Input::isKeyDown(SDL_SCANCODE_KP_3)) whichend = 3;
3215                         if (Input::isKeyDown(SDL_SCANCODE_KP_4)) whichend = 4;
3216                         if (Input::isKeyDown(SDL_SCANCODE_KP_5)) whichend = 5;
3217                         if (Input::isKeyDown(SDL_SCANCODE_KP_6)) whichend = 6;
3218                         if (Input::isKeyDown(SDL_SCANCODE_KP_7)) whichend = 7;
3219                         if (Input::isKeyDown(SDL_SCANCODE_KP_8)) whichend = 8;
3220                         if (Input::isKeyDown(SDL_SCANCODE_KP_9)) whichend = 9;
3221                         if (Input::isKeyDown(SDL_SCANCODE_KP_0)) whichend = 0;
3222                         Dialog::currentScene().participantfacing[whichend] = facing;
3223                     }
3224                     if (Dialog::indialogue >= int(Dialog::currentDialog().scenes.size())) {
3225                         Dialog::indialogue = -1;
3226                         Dialog::directing = false;
3227                         cameramode = 0;
3228                     }
3229                 }
3230                 if (!Dialog::directing) {
3231                     pause_sound(whooshsound);
3232                     viewer = Dialog::currentScene().camera;
3233                     viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .1);
3234                     yaw = Dialog::currentScene().camerayaw;
3235                     pitch = Dialog::currentScene().camerapitch;
3236                     if (Dialog::dialoguetime > 0.5) {
3237                         if (Input::isKeyPressed(attackkey)) {
3238                             Dialog::indialogue++;
3239                             if (Dialog::indialogue < int(Dialog::currentDialog().scenes.size())) {
3240                                 if (Dialog::currentScene().sound != 0) {
3241                                     playdialoguescenesound();
3242                                     if (Dialog::currentScene().sound == -5) {
3243                                         Hotspot::hotspots.emplace_back(Person::players[0]->coords, -1, 10);
3244                                     }
3245                                     if (Dialog::currentScene().sound == -6) {
3246                                         hostile = 1;
3247                                     }
3248
3249                                     if (Person::players[Dialog::currentScene().participantfocus]->dead) {
3250                                         Dialog::indialogue = -1;
3251                                         Dialog::directing = false;
3252                                         cameramode = 0;
3253                                     }
3254                                 }
3255                             }
3256                         }
3257                     }
3258                     if (Dialog::indialogue >= int(Dialog::currentDialog().scenes.size())) {
3259                         Dialog::indialogue = -1;
3260                         Dialog::directing = false;
3261                         cameramode = 0;
3262                         if (Dialog::currentDialog().type > 19 && Dialog::currentDialog().type < 30) {
3263                             hostile = 1;
3264                         }
3265                         if (Dialog::currentDialog().type > 29 && Dialog::currentDialog().type < 40) {
3266                             windialogue = true;
3267                         }
3268                         if (Dialog::currentDialog().type > 49 && Dialog::currentDialog().type < 60) {
3269                             hostile = 1;
3270                             for (unsigned i = 1; i < Person::players.size(); i++) {
3271                                 Person::players[i]->aitype = attacktypecutoff;
3272                             }
3273                         }
3274                     }
3275                 }
3276             }
3277
3278             if (!Person::players[0]->jumpkeydown) {
3279                 Person::players[0]->jumptogglekeydown = 0;
3280             }
3281             if (Person::players[0]->jumpkeydown &&
3282                     Person::players[0]->animTarget != jumpupanim &&
3283                     Person::players[0]->animTarget != jumpdownanim &&
3284                     !Person::players[0]->isFlip())
3285                 Person::players[0]->jumptogglekeydown = 1;
3286
3287
3288             Dialog::dialoguetime += multiplier;
3289             hawkyaw += multiplier * 25;
3290             realhawkcoords = 0;
3291             realhawkcoords.x = 25;
3292             realhawkcoords = DoRotation(realhawkcoords, 0, hawkyaw, 0) + hawkcoords;
3293             hawkcalldelay -= multiplier / 2;
3294
3295             if (hawkcalldelay <= 0) {
3296                 emit_sound_at(hawksound, realhawkcoords);
3297
3298                 hawkcalldelay = 16 + abs(Random() % 8);
3299             }
3300
3301             doDevKeys();
3302
3303             doAttacks();
3304
3305             doPlayerCollisions();
3306
3307             doJumpReversals();
3308
3309             for (unsigned k = 0; k < Person::players.size(); k++)
3310                 if (k != 0 && Person::players[k]->immobile)
3311                     Person::players[k]->coords = Person::players[k]->realoldcoords;
3312
3313             for (unsigned k = 0; k < Person::players.size(); k++) {
3314                 if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
3315                     if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
3316                         Person::players[k]->DoDamage(1000);
3317                     }
3318                 }
3319             }
3320
3321             //respawn
3322             static bool respawnkeydown;
3323             if (!editorenabled &&
3324                     (whichlevel != -2 &&
3325                      (Input::isKeyDown(SDL_SCANCODE_Z) &&
3326                       Input::isKeyDown(SDL_SCANCODE_LGUI) &&
3327                       devtools) ||
3328                      (Input::isKeyDown(jumpkey) &&
3329                       !respawnkeydown &&
3330                       !oldattackkey &&
3331                       Person::players[0]->dead))) {
3332                 targetlevel = whichlevel;
3333                 loading = 1;
3334                 leveltime = 5;
3335             }
3336             respawnkeydown = Input::isKeyDown(jumpkey);
3337
3338
3339             static bool movekey;
3340
3341             //?
3342             for (unsigned i = 0; i < Person::players.size(); i++) {
3343                 static float oldtargetyaw;
3344                 if (!Person::players[i]->skeleton.free) {
3345                     oldtargetyaw = Person::players[i]->targetyaw;
3346                     if (i == 0 && !Dialog::inDialog()) {
3347                         //TODO: refactor repetitive code
3348                         if (!Animation::animations[Person::players[0]->animTarget].attack &&
3349                                 Person::players[0]->animTarget != staggerbackhighanim &&
3350                                 Person::players[0]->animTarget != staggerbackhardanim &&
3351                                 Person::players[0]->animTarget != crouchremoveknifeanim &&
3352                                 Person::players[0]->animTarget != removeknifeanim &&
3353                                 Person::players[0]->animTarget != backhandspringanim &&
3354                                 Person::players[0]->animTarget != dodgebackanim &&
3355                                 Person::players[0]->animTarget != walljumprightkickanim &&
3356                                 Person::players[0]->animTarget != walljumpleftkickanim) {
3357                             if (cameramode)
3358                                 Person::players[0]->targetyaw = 0;
3359                             else
3360                                 Person::players[0]->targetyaw = -yaw + 180;
3361                         }
3362
3363                         facing = 0;
3364                         facing.z = -1;
3365
3366                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
3367                         if (cameramode) {
3368                             facing = flatfacing;
3369                         } else {
3370                             facing = DoRotation(facing, -pitch, 0, 0);
3371                             facing = DoRotation(facing, 0, 0 - yaw, 0);
3372                         }
3373
3374                         Person::players[0]->lookyaw = -yaw;
3375
3376                         Person::players[i]->targetheadyaw = yaw;
3377                         Person::players[i]->targetheadpitch = pitch;
3378                     }
3379                     if (i != 0 && Person::players[i]->aitype == playercontrolled && !Dialog::inDialog()) {
3380                         if (!Animation::animations[Person::players[i]->animTarget].attack &&
3381                                 Person::players[i]->animTarget != staggerbackhighanim &&
3382                                 Person::players[i]->animTarget != staggerbackhardanim &&
3383                                 Person::players[i]->animTarget != crouchremoveknifeanim &&
3384                                 Person::players[i]->animTarget != removeknifeanim &&
3385                                 Person::players[i]->animTarget != backhandspringanim &&
3386                                 Person::players[i]->animTarget != dodgebackanim &&
3387                                 Person::players[i]->animTarget != walljumprightkickanim &&
3388                                 Person::players[i]->animTarget != walljumpleftkickanim) {
3389                             Person::players[i]->targetyaw = -Person::players[i]->lookyaw + 180;
3390                         }
3391
3392                         facing = 0;
3393                         facing.z = -1;
3394
3395                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
3396
3397                         facing = DoRotation(facing, -Person::players[i]->lookpitch, 0, 0);
3398                         facing = DoRotation(facing, 0, 0 - Person::players[i]->lookyaw, 0);
3399
3400                         Person::players[i]->targetheadyaw = Person::players[i]->lookyaw;
3401                         Person::players[i]->targetheadpitch = Person::players[i]->lookpitch;
3402                     }
3403                     if (Dialog::inDialog()) {
3404                         Person::players[i]->targetheadyaw = 180 - roughDirection(Dialog::currentScene().participantfacing[i]);
3405                         Person::players[i]->targetheadpitch = pitchOf(Dialog::currentScene().participantfacing[i]);
3406                     }
3407
3408                     if (leveltime < .5)
3409                         numenvsounds = 0;
3410
3411                     Person::players[i]->avoidsomething = 0;
3412
3413                     //avoid flaming things
3414                     for (int j = 0; j < Object::objects.size(); j++)
3415                         if (Object::objects[j]->onfire)
3416                             if (distsq(&Person::players[i]->coords, &Object::objects[j]->position) < sq(Object::objects[j]->scale) * 200)
3417                                 if (     distsq(&Person::players[i]->coords, &Object::objects[j]->position) <
3418                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
3419                                     Person::players[i]->collided = 0;
3420                                     Person::players[i]->avoidcollided = 1;
3421                                     if (Person::players[i]->avoidsomething == 0 ||
3422                                             distsq(&Person::players[i]->coords, &Object::objects[j]->position) <
3423                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
3424                                         Person::players[i]->avoidwhere = Object::objects[j]->position;
3425                                         Person::players[i]->avoidsomething = 1;
3426                                     }
3427                                 }
3428
3429                     //avoid flaming players
3430                     for (unsigned j = 0; j < Person::players.size(); j++)
3431                         if (Person::players[j]->onfire)
3432                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < sq(0.3) * 200)
3433                                 if (     distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
3434                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
3435                                     Person::players[i]->collided = 0;
3436                                     Person::players[i]->avoidcollided = 1;
3437                                     if (Person::players[i]->avoidsomething == 0 ||
3438                                             distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
3439                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
3440                                         Person::players[i]->avoidwhere = Person::players[j]->coords;
3441                                         Person::players[i]->avoidsomething = 1;
3442                                     }
3443                                 }
3444
3445                     if (Person::players[i]->collided > .8)
3446                         Person::players[i]->avoidcollided = 0;
3447
3448                     Person::players[i]->doAI();
3449
3450                     if (Animation::animations[Person::players[i]->animTarget].attack == reversed) {
3451                         //Person::players[i]->targetyaw=Person::players[i]->yaw;
3452                         Person::players[i]->forwardkeydown = 0;
3453                         Person::players[i]->leftkeydown = 0;
3454                         Person::players[i]->backkeydown = 0;
3455                         Person::players[i]->rightkeydown = 0;
3456                         Person::players[i]->jumpkeydown = 0;
3457                         Person::players[i]->attackkeydown = 0;
3458                         //Person::players[i]->crouchkeydown=0;
3459                         Person::players[i]->throwkeydown = 0;
3460                     }
3461
3462                     if (Dialog::inDialog()) {
3463                         Person::players[i]->forwardkeydown = 0;
3464                         Person::players[i]->leftkeydown = 0;
3465                         Person::players[i]->backkeydown = 0;
3466                         Person::players[i]->rightkeydown = 0;
3467                         Person::players[i]->jumpkeydown = 0;
3468                         Person::players[i]->crouchkeydown = 0;
3469                         Person::players[i]->drawkeydown = 0;
3470                         Person::players[i]->throwkeydown = 0;
3471                     }
3472
3473                     if (Person::players[i]->collided < -.3)
3474                         Person::players[i]->collided = -.3;
3475                     if (Person::players[i]->collided > 1)
3476                         Person::players[i]->collided = 1;
3477                     Person::players[i]->collided -= multiplier * 4;
3478                     Person::players[i]->whichdirectiondelay -= multiplier;
3479                     if (Person::players[i]->avoidcollided < -.3 || Person::players[i]->whichdirectiondelay <= 0) {
3480                         Person::players[i]->avoidcollided = -.3;
3481                         Person::players[i]->whichdirection = abs(Random() % 2);
3482                         Person::players[i]->whichdirectiondelay = .4;
3483                     }
3484                     if (Person::players[i]->avoidcollided > 1)
3485                         Person::players[i]->avoidcollided = 1;
3486                     Person::players[i]->avoidcollided -= multiplier / 4;
3487                     if (!Person::players[i]->skeleton.free) {
3488                         Person::players[i]->stunned -= multiplier;
3489                         Person::players[i]->surprised -= multiplier;
3490                     }
3491                     if (i != 0 && Person::players[i]->surprised <= 0 &&
3492                             Person::players[i]->aitype == attacktypecutoff &&
3493                             !Person::players[i]->dead &&
3494                             !Person::players[i]->skeleton.free &&
3495                             Animation::animations[Person::players[i]->animTarget].attack == neutral)
3496                         numresponded = 1;
3497
3498                     if (!Person::players[i]->throwkeydown)
3499                         Person::players[i]->throwtogglekeydown = 0;
3500
3501                     //pick up weapon
3502                     if (Person::players[i]->throwkeydown && !Person::players[i]->throwtogglekeydown) {
3503                         if (Person::players[i]->weaponactive == -1 &&
3504                                 Person::players[i]->num_weapons < 2 &&
3505                                 (Person::players[i]->isIdle() ||
3506                                  Person::players[i]->isCrouch() ||
3507                                  Person::players[i]->animTarget == sneakanim ||
3508                                  Person::players[i]->animTarget == rollanim ||
3509                                  Person::players[i]->animTarget == backhandspringanim ||
3510                                  Person::players[i]->isFlip() ||
3511                                  Person::players[i]->aitype != playercontrolled)) {
3512                             for (unsigned j = 0; j < weapons.size(); j++) {
3513                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
3514                                         Person::players[i]->aitype == playercontrolled) &&
3515                                         weapons[j].owner == -1 &&
3516                                         Person::players[i]->weaponactive == -1)
3517                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2) {
3518                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 2) {
3519                                             if (Person::players[i]->isCrouch() ||
3520                                                     Person::players[i]->animTarget == sneakanim ||
3521                                                     Person::players[i]->isRun() ||
3522                                                     Person::players[i]->isIdle() ||
3523                                                     Person::players[i]->aitype != playercontrolled) {
3524                                                 Person::players[i]->throwtogglekeydown = 1;
3525                                                 Person::players[i]->setAnimation(crouchremoveknifeanim);
3526                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
3527                                                 Person::players[i]->hasvictim = 0;
3528                                             }
3529                                             if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
3530                                                 Person::players[i]->throwtogglekeydown = 1;
3531                                                 Person::players[i]->hasvictim = 0;
3532
3533                                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
3534                                                         Person::players[i]->aitype == playercontrolled) &&
3535                                                         weapons[j].owner == -1 ||
3536                                                         Person::players[i]->victim &&
3537                                                         weapons[j].owner == int(Person::players[i]->victim->id))
3538                                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2 && Person::players[i]->weaponactive == -1)
3539                                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 1 || Person::players[i]->victim) {
3540                                                             if (weapons[j].getType() != staff)
3541                                                                 emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
3542
3543                                                             Person::players[i]->takeWeapon(j);
3544                                                         }
3545                                             }
3546                                         } else if ((Person::players[i]->isIdle() ||
3547                                                     Person::players[i]->isFlip() ||
3548                                                     Person::players[i]->aitype != playercontrolled) &&
3549                                                    distsq(&Person::players[i]->coords, &weapons[j].position) < 5 &&
3550                                                    Person::players[i]->coords.y < weapons[j].position.y) {
3551                                             if (!Person::players[i]->isFlip()) {
3552                                                 Person::players[i]->throwtogglekeydown = 1;
3553                                                 Person::players[i]->setAnimation(removeknifeanim);
3554                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
3555                                             }
3556                                             if (Person::players[i]->isFlip()) {
3557                                                 Person::players[i]->throwtogglekeydown = 1;
3558                                                 Person::players[i]->hasvictim = 0;
3559
3560                                                 for (unsigned k = 0; k < weapons.size(); k++) {
3561                                                     if (Person::players[i]->weaponactive == -1)
3562                                                         if ((weapons[k].velocity.x == 0 && weapons[k].velocity.y == 0 && weapons[k].velocity.z == 0 ||
3563                                                                 Person::players[i]->aitype == playercontrolled) &&
3564                                                                 weapons[k].owner == -1 ||
3565                                                                 Person::players[i]->victim &&
3566                                                                 weapons[k].owner == int(Person::players[i]->victim->id))
3567                                                             if (distsqflat(&Person::players[i]->coords, &weapons[k].position) < 3 &&
3568                                                                     Person::players[i]->weaponactive == -1) {
3569                                                                 if (weapons[k].getType() != staff)
3570                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
3571
3572                                                                 Person::players[i]->takeWeapon(k);
3573                                                             }
3574                                                 }
3575                                             }
3576                                         }
3577                                     }
3578                             }
3579                             if (Person::players[i]->isCrouch() ||
3580                                     Person::players[i]->animTarget == sneakanim ||
3581                                     Person::players[i]->isRun() ||
3582                                     Person::players[i]->isIdle() || Person::players[i]->animTarget == rollanim ||
3583                                     Person::players[i]->animTarget == backhandspringanim) {
3584                                 if (Person::players.size() > 1)
3585                                     for (unsigned j = 0; j < Person::players.size(); j++) {
3586                                         if (Person::players[i]->weaponactive == -1)
3587                                             if (j != i)
3588                                                 if (Person::players[j]->num_weapons &&
3589                                                         Person::players[j]->skeleton.free &&
3590                                                         distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 2/*&&Person::players[j]->dead*/ &&
3591                                                         (((Person::players[j]->skeleton.forward.y < 0 &&
3592                                                            Person::players[j]->weaponstuckwhere == 0) ||
3593                                                           (Person::players[j]->skeleton.forward.y > 0 &&
3594                                                            Person::players[j]->weaponstuckwhere == 1)) ||
3595                                                          Person::players[j]->weaponstuck == -1 ||
3596                                                          Person::players[j]->num_weapons > 1)) {
3597                                                     if (Person::players[i]->animTarget != rollanim && Person::players[i]->animTarget != backhandspringanim) {
3598                                                         Person::players[i]->throwtogglekeydown = 1;
3599                                                         Person::players[i]->victim = Person::players[j];
3600                                                         Person::players[i]->hasvictim = 1;
3601                                                         Person::players[i]->setAnimation(crouchremoveknifeanim);
3602                                                         Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
3603                                                     }
3604                                                     if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
3605                                                         Person::players[i]->throwtogglekeydown = 1;
3606                                                         Person::players[i]->victim = Person::players[j];
3607                                                         Person::players[i]->hasvictim = 1;
3608                                                         int k = Person::players[j]->weaponids[0];
3609                                                         if (Person::players[i]->hasvictim) {
3610                                                             bool fleshstuck;
3611                                                             fleshstuck = 0;
3612                                                             if (Person::players[i]->victim->weaponstuck != -1) {
3613                                                                 if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
3614                                                                     fleshstuck = 1;
3615                                                                 }
3616                                                             }
3617                                                             if (!fleshstuck) {
3618                                                                 if (weapons[k].getType() != staff)
3619                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
3620                                                             }
3621                                                             if (fleshstuck)
3622                                                                 emit_sound_at(fleshstabremovesound, Person::players[i]->coords, 128.);
3623
3624                                                             if (weapons[k].owner != -1) {
3625                                                                 if (Person::players[i]->victim->num_weapons == 1)
3626                                                                     Person::players[i]->victim->num_weapons = 0;
3627                                                                 else
3628                                                                     Person::players[i]->victim->num_weapons = 1;
3629
3630                                                                 Person::players[i]->victim->skeleton.longdead = 0;
3631                                                                 Person::players[i]->victim->skeleton.free = 1;
3632                                                                 Person::players[i]->victim->skeleton.broken = 0;
3633
3634                                                                 for (unsigned l = 0; l < Person::players[i]->victim->skeleton.joints.size(); l++) {
3635                                                                     Person::players[i]->victim->skeleton.joints[l].velchange = 0;
3636                                                                     Person::players[i]->victim->skeleton.joints[l].locked = 0;
3637                                                                 }
3638
3639                                                                 XYZ relative;
3640                                                                 relative = 0;
3641                                                                 relative.y = 10;
3642                                                                 Normalise(&relative);
3643                                                                 XYZ footvel, footpoint;
3644                                                                 footvel = 0;
3645                                                                 footpoint = weapons[k].position;
3646                                                                 if (Person::players[i]->victim->weaponstuck != -1) {
3647                                                                     if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
3648                                                                         if (bloodtoggle)
3649                                                                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3650                                                                         weapons[k].bloody = 2;
3651                                                                         weapons[k].blooddrip = 5;
3652                                                                         Person::players[i]->victim->weaponstuck = -1;
3653                                                                         Person::players[i]->victim->bloodloss += 2000;
3654                                                                         Person::players[i]->victim->DoDamage(2000);
3655                                                                     }
3656                                                                 }
3657                                                                 if (Person::players[i]->victim->num_weapons > 0) {
3658                                                                     if (Person::players[i]->victim->weaponstuck != 0 && Person::players[i]->victim->weaponstuck != -1)
3659                                                                         Person::players[i]->victim->weaponstuck = 0;
3660                                                                     if (Person::players[i]->victim->weaponids[0] == k)
3661                                                                         Person::players[i]->victim->weaponids[0] = Person::players[i]->victim->weaponids[Person::players[i]->victim->num_weapons];
3662                                                                 }
3663
3664                                                                 Person::players[i]->victim->weaponactive = -1;
3665
3666                                                                 Person::players[i]->victim->jointVel(abdomen) += relative * 6;
3667                                                                 Person::players[i]->victim->jointVel(neck) += relative * 6;
3668                                                                 Person::players[i]->victim->jointVel(rightshoulder) += relative * 6;
3669                                                                 Person::players[i]->victim->jointVel(leftshoulder) += relative * 6;
3670                                                             }
3671                                                             Person::players[i]->takeWeapon(k);
3672                                                         }
3673                                                     }
3674                                                 }
3675                                     }
3676                             }
3677                         }
3678                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
3679                             if (weapons[Person::players[i]->weaponids[0]].getType() == knife) {
3680                                 if (Person::players[i]->isIdle() ||
3681                                         Person::players[i]->isRun() ||
3682                                         Person::players[i]->isCrouch() ||
3683                                         Person::players[i]->animTarget == sneakanim ||
3684                                         Person::players[i]->isFlip())
3685                                     if (Person::players.size() > 1)
3686                                         for (unsigned j = 0; j < Person::players.size(); j++) {
3687                                             if (i != j)
3688                                                 if (!Tutorial::active || Tutorial::stage == 49)
3689                                                     if (hostile)
3690                                                         if (normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0 &&
3691                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 100 &&
3692                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) > 1.5 &&
3693                                                                 !Person::players[j]->skeleton.free &&
3694                                                                 -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)) {
3695                                                             if (!Person::players[i]->isFlip()) {
3696                                                                 Person::players[i]->throwtogglekeydown = 1;
3697                                                                 Person::players[i]->victim = Person::players[j];
3698                                                                 Person::players[i]->setAnimation(knifethrowanim);
3699                                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
3700                                                                 Person::players[i]->targettilt2 = pitchTo(Person::players[i]->coords, Person::players[j]->coords);
3701                                                             }
3702                                                             if (Person::players[i]->isFlip()) {
3703                                                                 if (Person::players[i]->weaponactive != -1) {
3704                                                                     Person::players[i]->throwtogglekeydown = 1;
3705                                                                     Person::players[i]->victim = Person::players[j];
3706                                                                     XYZ aim;
3707                                                                     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);
3708                                                                     Normalise(&aim);
3709
3710                                                                     aim = DoRotation(aim, (float)abs(Random() % 30) - 15, (float)abs(Random() % 30) - 15, 0);
3711
3712                                                                     weapons[Person::players[i]->weaponids[0]].thrown(aim * 50, false);
3713                                                                     Person::players[i]->num_weapons--;
3714                                                                     if (Person::players[i]->num_weapons) {
3715                                                                         Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
3716                                                                     }
3717                                                                     Person::players[i]->weaponactive = -1;
3718                                                                 }
3719                                                             }
3720                                                         }
3721                                         }
3722                             }
3723                         }
3724                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
3725                             if (Person::players[i]->isCrouch() || Person::players[i]->animTarget == sneakanim) {
3726                                 Person::players[i]->throwtogglekeydown = 1;
3727                                 XYZ tempVelocity = Person::players[i]->velocity * .2;
3728                                 if (tempVelocity.x == 0)
3729                                     tempVelocity.x = .1;
3730                                 weapons[Person::players[i]->weaponids[0]].drop(tempVelocity, tempVelocity, false);
3731                                 Person::players[i]->num_weapons--;
3732                                 if (Person::players[i]->num_weapons) {
3733                                     Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
3734                                     if (Person::players[i]->weaponstuck == Person::players[i]->num_weapons)
3735                                         Person::players[i]->weaponstuck = 0;
3736                                 }
3737
3738                                 Person::players[i]->weaponactive = -1;
3739                                 for (unsigned j = 0; j < Person::players.size(); j++) {
3740                                     Person::players[j]->wentforweapon = 0;
3741                                 }
3742                             }
3743                         }
3744
3745                     }
3746
3747                     //draw weapon
3748                     if (i == 0 || !Person::players[0]->dead || (Person::players[i]->weaponactive != -1)) {
3749                         if (Person::players[i]->drawkeydown && !Person::players[i]->drawtogglekeydown ||
3750                                 (Person::players[i]->num_weapons == 2) &&
3751                                 (Person::players[i]->weaponactive == -1) &&
3752                                 Person::players[i]->isIdle() ||
3753                                 Person::players[0]->dead &&
3754                                 (Person::players[i]->weaponactive != -1) &&
3755                                 i != 0) {
3756                             bool isgood = true;
3757                             if (Person::players[i]->weaponactive != -1)
3758                                 if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == staff)
3759                                     isgood = false;
3760                             if (isgood && Person::players[i]->creature != wolftype) {
3761                                 if (Person::players[i]->isIdle() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
3762                                     Person::players[i]->setAnimation(drawrightanim);
3763                                     Person::players[i]->drawtogglekeydown = 1;
3764                                 }
3765                                 if ((Person::players[i]->isIdle() ||
3766                                         (Person::players[i]->aitype != playercontrolled &&
3767                                          Person::players[0]->weaponactive != -1 &&
3768                                          Person::players[i]->isRun())) &&
3769                                         Person::players[i]->num_weapons &&
3770                                         weapons[Person::players[i]->weaponids[0]].getType() == sword) {
3771                                     Person::players[i]->setAnimation(drawleftanim);
3772                                     Person::players[i]->drawtogglekeydown = 1;
3773                                 }
3774                                 if (Person::players[i]->isCrouch() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
3775                                     Person::players[i]->setAnimation(crouchdrawrightanim);
3776                                     Person::players[i]->drawtogglekeydown = 1;
3777                                 }
3778                             }
3779                         }
3780                     }
3781
3782                     //clean weapon
3783                     if (Person::players[i]->weaponactive != -1) {
3784                         if (Person::players[i]->isCrouch() &&
3785                                 weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].bloody &&
3786                                 bloodtoggle &&
3787                                 Person::players[i]->onterrain &&
3788                                 Person::players[i]->num_weapons &&
3789                                 Person::players[i]->attackkeydown &&
3790                                 musictype != stream_fighttheme) {
3791                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == knife)
3792                                 Person::players[i]->setAnimation(crouchstabanim);
3793                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == sword)
3794                                 Person::players[i]->setAnimation(swordgroundstabanim);
3795                             Person::players[i]->hasvictim = 0;
3796                         }
3797                     }
3798
3799                     if (!Person::players[i]->drawkeydown)
3800                         Person::players[i]->drawtogglekeydown = 0;
3801
3802                     XYZ absflatfacing;
3803                     if (i == 0) {
3804                         absflatfacing = 0;
3805                         absflatfacing.z = -1;
3806
3807                         absflatfacing = DoRotation(absflatfacing, 0, -yaw, 0);
3808                     } else
3809                         absflatfacing = flatfacing;
3810
3811                     if (Dialog::inDialog()) {
3812                         Person::players[i]->forwardkeydown = 0;
3813                         Person::players[i]->leftkeydown = 0;
3814                         Person::players[i]->backkeydown = 0;
3815                         Person::players[i]->rightkeydown = 0;
3816                         Person::players[i]->jumpkeydown = 0;
3817                         Person::players[i]->crouchkeydown = 0;
3818                         Person::players[i]->drawkeydown = 0;
3819                         Person::players[i]->throwkeydown = 0;
3820                     }
3821                     movekey = 0;
3822                     //Do controls
3823                     if (!Animation::animations[Person::players[i]->animTarget].attack &&
3824                             Person::players[i]->animTarget != staggerbackhighanim &&
3825                             Person::players[i]->animTarget != staggerbackhardanim &&
3826                             Person::players[i]->animTarget != backhandspringanim &&
3827                             Person::players[i]->animTarget != dodgebackanim) {
3828                         if (!Person::players[i]->forwardkeydown)
3829                             Person::players[i]->forwardstogglekeydown = 0;
3830                         if (Person::players[i]->crouchkeydown) {
3831                             //Crouch
3832                             target = -2;
3833                             if (i == 0) {
3834                                 Person::players[i]->superruntoggle = 1;
3835                                 if (Person::players.size() > 1)
3836                                     for (unsigned j = 0; j < Person::players.size(); j++)
3837                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->aitype == passivetype)
3838                                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 16)
3839                                                 Person::players[i]->superruntoggle = 0;
3840                             }
3841
3842                             if (Person::players.size() > 1)
3843                                 for (unsigned j = 0; j < Person::players.size(); j++) {
3844                                     if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim && Person::players[i]->lowreversaldelay <= 0) {
3845                                         if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
3846                                                 Person::players[j]->victim == Person::players[i] &&
3847                                                 (Person::players[j]->animTarget == sweepanim ||
3848                                                  Person::players[j]->animTarget == upunchanim ||
3849                                                  Person::players[j]->animTarget == wolfslapanim ||
3850                                                  ((Person::players[j]->animTarget == swordslashanim ||
3851                                                    Person::players[j]->animTarget == knifeslashstartanim ||
3852                                                    Person::players[j]->animTarget == staffhitanim ||
3853                                                    Person::players[j]->animTarget == staffspinhitanim) &&
3854                                                   distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2))) {
3855                                             if (target >= 0)
3856                                                 target = -1;
3857                                             else
3858                                                 target = j;
3859                                         }
3860                                     }
3861                                 }
3862                             if (target >= 0)
3863                                 Person::players[target]->Reverse();
3864                             Person::players[i]->lowreversaldelay = .5;
3865
3866                             if (Person::players[i]->isIdle()) {
3867                                 Person::players[i]->setAnimation(Person::players[i]->getCrouch());
3868                                 Person::players[i]->transspeed = 10;
3869                             }
3870                             if (Person::players[i]->isRun() ||
3871                                     (Person::players[i]->isStop() &&
3872                                      (Person::players[i]->leftkeydown ||
3873                                       Person::players[i]->rightkeydown ||
3874                                       Person::players[i]->forwardkeydown ||
3875                                       Person::players[i]->backkeydown))) {
3876                                 Person::players[i]->setAnimation(rollanim);
3877                                 Person::players[i]->transspeed = 20;
3878                             }
3879                         }
3880                         if (!Person::players[i]->crouchkeydown) {
3881                             //Uncrouch
3882                             if (!Person::players[i]->isRun() && Person::players[i]->animTarget != sneakanim && i == 0)
3883                                 Person::players[i]->superruntoggle = 0;
3884                             target = -2;
3885                             if (Person::players[i]->isCrouch()) {
3886                                 if (Person::players.size() > 1)
3887                                     for (unsigned j = 0; j < Person::players.size(); j++) {
3888                                         if (j != i &&
3889                                                 !Person::players[j]->skeleton.free &&
3890                                                 Person::players[j]->victim &&
3891                                                 Person::players[i]->highreversaldelay <= 0) {
3892                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
3893                                                     Person::players[j]->victim == Person::players[i] &&
3894                                                     (Person::players[j]->animTarget == spinkickanim) &&
3895                                                     Person::players[i]->isCrouch()) {
3896                                                 if (target >= 0)
3897                                                     target = -1;
3898                                                 else
3899                                                     target = j;
3900                                             }
3901                                         }
3902                                     }
3903                                 if (target >= 0)
3904                                     Person::players[target]->Reverse();
3905                                 Person::players[i]->highreversaldelay = .5;
3906
3907                                 if (Person::players[i]->isCrouch()) {
3908                                     if (!Person::players[i]->wasCrouch()) {
3909                                         Person::players[i]->animCurrent = Person::players[i]->getCrouch();
3910                                         Person::players[i]->frameCurrent = 0;
3911                                     }
3912                                     Person::players[i]->setAnimation(Person::players[i]->getIdle());
3913                                     Person::players[i]->transspeed = 10;
3914                                 }
3915                             }
3916                             if (Person::players[i]->animTarget == sneakanim) {
3917                                 Person::players[i]->setAnimation(Person::players[i]->getIdle());
3918                                 Person::players[i]->transspeed = 10;
3919                             }
3920                         }
3921                         if (Person::players[i]->forwardkeydown) {
3922                             if (Person::players[i]->isIdle() ||
3923                                     (Person::players[i]->isStop() &&
3924                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
3925                                     (Person::players[i]->isLanding() &&
3926                                      Person::players[i]->frameTarget > 0 &&
3927                                      !Person::players[i]->jumpkeydown) ||
3928                                     (Person::players[i]->isLandhard() &&
3929                                      Person::players[i]->frameTarget > 0 &&
3930                                      !Person::players[i]->jumpkeydown &&
3931                                      Person::players[i]->crouchkeydown)) {
3932                                 if (Person::players[i]->aitype == passivetype)
3933                                     Person::players[i]->setAnimation(walkanim);
3934                                 else
3935                                     Person::players[i]->setAnimation(Person::players[i]->getRun());
3936                             }
3937                             if (Person::players[i]->isCrouch()) {
3938                                 Person::players[i]->animTarget = sneakanim;
3939                                 if (Person::players[i]->wasCrouch())
3940                                     Person::players[i]->target = 0;
3941                                 Person::players[i]->frameTarget = 0;
3942                             }
3943                             if (Person::players[i]->animTarget == hanganim/*&&(!Person::players[i]->forwardstogglekeydown||Person::players[i]->aitype!=playercontrolled)*/) {
3944                                 Person::players[i]->setAnimation(climbanim);
3945                                 Person::players[i]->frameTarget = 1;
3946                                 Person::players[i]->jumpclimb = 1;
3947                             }
3948                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
3949                                 Person::players[i]->velocity += absflatfacing * 5 * multiplier;
3950                             }
3951                             Person::players[i]->forwardstogglekeydown = 1;
3952                             movekey = 1;
3953                         }
3954                         if (Person::players[i]->rightkeydown) {
3955                             if (Person::players[i]->isIdle() ||
3956                                     (Person::players[i]->isStop() &&
3957                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
3958                                     (Person::players[i]->isLanding() &&
3959                                      Person::players[i]->frameTarget > 0 &&
3960                                      !Person::players[i]->jumpkeydown) ||
3961                                     (Person::players[i]->isLandhard() &&
3962                                      Person::players[i]->frameTarget > 0 &&
3963                                      !Person::players[i]->jumpkeydown &&
3964                                      Person::players[i]->crouchkeydown)) {
3965                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
3966                             }
3967                             if (Person::players[i]->isCrouch()) {
3968                                 Person::players[i]->animTarget = sneakanim;
3969                                 if (Person::players[i]->wasCrouch())
3970                                     Person::players[i]->target = 0;
3971                                 Person::players[i]->frameTarget = 0;
3972                             }
3973                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
3974                                 Person::players[i]->velocity += DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
3975                             }
3976                             Person::players[i]->targetyaw -= 90;
3977                             if (Person::players[i]->forwardkeydown)
3978                                 Person::players[i]->targetyaw += 45;
3979                             if (Person::players[i]->backkeydown)
3980                                 Person::players[i]->targetyaw -= 45;
3981                             movekey = 1;
3982                         }
3983                         if ( Person::players[i]->leftkeydown) {
3984                             if (Person::players[i]->isIdle() ||
3985                                     (Person::players[i]->isStop() &&
3986                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
3987                                     (Person::players[i]->isLanding() &&
3988                                      Person::players[i]->frameTarget > 0 &&
3989                                      !Person::players[i]->jumpkeydown) ||
3990                                     (Person::players[i]->isLandhard() &&
3991                                      Person::players[i]->frameTarget > 0 &&
3992                                      !Person::players[i]->jumpkeydown &&
3993                                      Person::players[i]->crouchkeydown)) {
3994                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
3995                             }
3996                             if (Person::players[i]->isCrouch()) {
3997                                 Person::players[i]->animTarget = sneakanim;
3998                                 if (Person::players[i]->wasCrouch())
3999                                     Person::players[i]->target = 0;
4000                                 Person::players[i]->frameTarget = 0;
4001                             }
4002                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
4003                                 Person::players[i]->velocity -= DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
4004                             }
4005                             Person::players[i]->targetyaw += 90;
4006                             if (Person::players[i]->forwardkeydown)
4007                                 Person::players[i]->targetyaw -= 45;
4008                             if (Person::players[i]->backkeydown)
4009                                 Person::players[i]->targetyaw += 45;
4010                             movekey = 1;
4011                         }
4012                         if (Person::players[i]->backkeydown) {
4013                             if (Person::players[i]->isIdle() ||
4014                                     (Person::players[i]->isStop() &&
4015                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
4016                                     (Person::players[i]->isLanding() &&
4017                                      Person::players[i]->frameTarget > 0 &&
4018                                      !Person::players[i]->jumpkeydown) ||
4019                                     (Person::players[i]->isLandhard() &&
4020                                      Person::players[i]->frameTarget > 0 &&
4021                                      !Person::players[i]->jumpkeydown &&
4022                                      Person::players[i]->crouchkeydown)) {
4023                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
4024                             }
4025                             if (Person::players[i]->isCrouch()) {
4026                                 Person::players[i]->animTarget = sneakanim;
4027                                 if (Person::players[i]->wasCrouch())
4028                                     Person::players[i]->target = 0;
4029                                 Person::players[i]->frameTarget = 0;
4030                             }
4031                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
4032                                 Person::players[i]->velocity -= absflatfacing * 5 * multiplier;
4033                             }
4034                             if (Person::players[i]->animTarget == hanganim) {
4035                                 Person::players[i]->animCurrent = jumpdownanim;
4036                                 Person::players[i]->animTarget = jumpdownanim;
4037                                 Person::players[i]->target = 0;
4038                                 Person::players[i]->frameCurrent = 0;
4039                                 Person::players[i]->frameTarget = 1;
4040                                 Person::players[i]->velocity = 0;
4041                                 Person::players[i]->velocity.y += gravity;
4042                                 Person::players[i]->coords.y -= 1.4;
4043                                 Person::players[i]->grabdelay = 1;
4044                             }
4045                             if ( !Person::players[i]->leftkeydown && !Person::players[i]->rightkeydown)
4046                                 Person::players[i]->targetyaw += 180;
4047                             movekey = 1;
4048                         }
4049                         if ((Person::players[i]->jumpkeydown && !Person::players[i]->jumpclimb) || Person::players[i]->jumpstart) {
4050                             if ((((Person::players[i]->isLanding() && Person::players[i]->frameTarget >= 3) ||
4051                                     Person::players[i]->isRun() ||
4052                                     Person::players[i]->animTarget == walkanim ||
4053                                     Person::players[i]->isCrouch() ||
4054                                     Person::players[i]->animTarget == sneakanim) &&
4055                                     Person::players[i]->jumppower > 1) &&
4056                                     ((Person::players[i]->animTarget != rabbitrunninganim &&
4057                                       Person::players[i]->animTarget != wolfrunninganim) || i != 0)) {
4058                                 Person::players[i]->jumpstart = 0;
4059                                 Person::players[i]->setAnimation(jumpupanim);
4060                                 Person::players[i]->yaw = Person::players[i]->targetyaw;
4061                                 Person::players[i]->transspeed = 20;
4062                                 Person::players[i]->FootLand(leftfoot, 1);
4063                                 Person::players[i]->FootLand(rightfoot, 1);
4064
4065                                 facing = 0;
4066                                 facing.z = -1;
4067                                 flatfacing = DoRotation(facing, 0, Person::players[i]->targetyaw + 180, 0);
4068
4069                                 if (movekey)
4070                                     Person::players[i]->velocity = flatfacing * Person::players[i]->speed * 45 * Person::players[i]->scale;
4071                                 if (!movekey)
4072                                     Person::players[i]->velocity = 0;
4073
4074                                 //Dodge sweep?
4075                                 target = -2;
4076                                 if (Person::players.size() > 1)
4077                                     for (unsigned j = 0; j < Person::players.size(); j++) {
4078                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim) {
4079                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
4080                                                     (Person::players[j]->victim == Person::players[i]) &&
4081                                                     (Person::players[j]->animTarget == sweepanim)) {
4082                                                 if (target >= 0)
4083                                                     target = -1;
4084                                                 else
4085                                                     target = j;
4086                                             }
4087                                         }
4088                                     }
4089                                 if (target >= 0)
4090                                     Person::players[i]->velocity.y = 1;
4091                                 else
4092                                     if (Person::players[i]->crouchkeydown || Person::players[i]->aitype != playercontrolled) {
4093                                     Person::players[i]->velocity.y = 7;
4094                                     Person::players[i]->crouchtogglekeydown = 1;
4095                                 } else Person::players[i]->velocity.y = 5;
4096
4097                                 if (mousejump && i == 0 && devtools) {
4098                                     if (!Person::players[i]->isLanding())
4099                                         Person::players[i]->tempdeltav = deltav;
4100                                     if (Person::players[i]->tempdeltav < 0)
4101                                         Person::players[i]->velocity.y -= (float)(Person::players[i]->tempdeltav) / multiplier / 1000;
4102                                 }
4103
4104                                 Person::players[i]->coords.y += .2;
4105                                 Person::players[i]->jumppower -= 1;
4106
4107                                 if (!i)
4108                                     emit_sound_at(whooshsound, Person::players[i]->coords, 128.);
4109
4110                                 emit_sound_at(jumpsound, Person::players[i]->coords, 128.);
4111                             }
4112                             if ((Person::players[i]->isIdle()) && Person::players[i]->jumppower > 1) {
4113                                 Person::players[i]->setAnimation(Person::players[i]->getLanding());
4114                                 Person::players[i]->frameTarget = 2;
4115                                 Person::players[i]->landhard = 0;
4116                                 Person::players[i]->jumpstart = 1;
4117                                 Person::players[i]->tempdeltav = deltav;
4118                             }
4119                             if (Person::players[i]->animTarget == jumpupanim &&
4120                                     (((!floatjump &&
4121                                        !editorenabled) ||
4122                                       !devtools) ||
4123                                      Person::players[i]->aitype != playercontrolled)) {
4124                                 if (Person::players[i]->jumppower > multiplier * 6) {
4125                                     Person::players[i]->velocity.y += multiplier * 6;
4126                                     Person::players[i]->jumppower -= multiplier * 6;
4127                                 }
4128                                 if (Person::players[i]->jumppower <= multiplier * 6) {
4129                                     Person::players[i]->velocity.y += Person::players[i]->jumppower;
4130                                     Person::players[i]->jumppower = 0;
4131                                 }
4132                             }
4133                             if (((floatjump || editorenabled) && devtools) && i == 0)
4134                                 Person::players[i]->velocity.y += multiplier * 30;
4135                         }
4136
4137                         if (!movekey) {
4138                             if (Person::players[i]->isRun() || Person::players[i]->animTarget == walkanim)
4139                                 Person::players[i]->setAnimation(Person::players[i]->getStop());
4140                             if (Person::players[i]->animTarget == sneakanim) {
4141                                 Person::players[i]->animTarget = Person::players[i]->getCrouch();
4142                                 if (Person::players[i]->animCurrent == sneakanim)
4143                                     Person::players[i]->target = 0;
4144                                 Person::players[i]->frameTarget = 0;
4145                             }
4146                         }
4147                         if (Person::players[i]->animTarget == walkanim &&
4148                                 (Person::players[i]->aitype == attacktypecutoff ||
4149                                  Person::players[i]->aitype == searchtype ||
4150                                  (Person::players[i]->aitype == passivetype &&
4151                                   Person::players[i]->numwaypoints <= 1)))
4152                             Person::players[i]->setAnimation(Person::players[i]->getStop());
4153                         if (Person::players[i]->isRun() && (Person::players[i]->aitype == passivetype))
4154                             Person::players[i]->setAnimation(Person::players[i]->getStop());
4155                     }
4156                 }
4157                 if (Person::players[i]->animTarget == rollanim)
4158                     Person::players[i]->targetyaw = oldtargetyaw;
4159             }
4160
4161             //Rotation
4162             for (unsigned k = 0; k < Person::players.size(); k++) {
4163                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 180) {
4164                     if (Person::players[k]->yaw > Person::players[k]->targetyaw)
4165                         Person::players[k]->yaw -= 360;
4166                     else
4167                         Person::players[k]->yaw += 360;
4168                 }
4169
4170                 //stop to turn in right direction
4171                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 90 && (Person::players[k]->isRun() || Person::players[k]->animTarget == walkanim))
4172                     Person::players[k]->setAnimation(Person::players[k]->getStop());
4173
4174                 if (Person::players[k]->animTarget == backhandspringanim || Person::players[k]->animTarget == dodgebackanim)
4175                     Person::players[k]->targettilt = 0;
4176
4177                 if (Person::players[k]->animTarget != jumpupanim &&
4178                         Person::players[k]->animTarget != backhandspringanim &&
4179                         Person::players[k]->animTarget != jumpdownanim &&
4180                         !Person::players[k]->isFlip()) {
4181                     Person::players[k]->targettilt = 0;
4182                     if (Person::players[k]->jumppower < 0 && !Person::players[k]->jumpkeydown)
4183                         Person::players[k]->jumppower = 0;
4184                     Person::players[k]->jumppower += multiplier * 7;
4185                     if (Person::players[k]->isCrouch())
4186                         Person::players[k]->jumppower += multiplier * 7;
4187                     if (Person::players[k]->jumppower > 5)
4188                         Person::players[k]->jumppower = 5;
4189                 }
4190
4191                 if (Person::players[k]->isRun())
4192                     Person::players[k]->targettilt = (Person::players[k]->yaw - Person::players[k]->targetyaw) / 4;
4193
4194                 Person::players[k]->tilt = stepTowardf(Person::players[k]->tilt, Person::players[k]->targettilt, multiplier * 150);
4195                 Person::players[k]->grabdelay -= multiplier;
4196             }
4197
4198             //do animations
4199             for (unsigned k = 0; k < Person::players.size(); k++) {
4200                 Person::players[k]->DoAnimations();
4201                 Person::players[k]->whichpatchx = Person::players[k]->coords.x / (terrain.size / subdivision * terrain.scale);
4202                 Person::players[k]->whichpatchz = Person::players[k]->coords.z / (terrain.size / subdivision * terrain.scale);
4203             }
4204
4205             //do stuff
4206             Object::DoStuff();
4207
4208             for (int j = numenvsounds - 1; j >= 0; j--) {
4209                 envsoundlife[j] -= multiplier;
4210                 if (envsoundlife[j] < 0) {
4211                     numenvsounds--;
4212                     envsoundlife[j] = envsoundlife[numenvsounds];
4213                     envsound[j] = envsound[numenvsounds];
4214                 }
4215             }
4216             OPENAL_SetFrequency(OPENAL_ALL, slomo);
4217
4218             if (Tutorial::active) {
4219                 Tutorial::DoStuff(multiplier);
4220             }
4221
4222
4223             //3d sound
4224             static float gLoc[3];
4225             gLoc[0] = viewer.x;
4226             gLoc[1] = viewer.y;
4227             gLoc[2] = viewer.z;
4228             static float vel[3];
4229             vel[0] = (viewer.x - oldviewer.x) / multiplier;
4230             vel[1] = (viewer.y - oldviewer.y) / multiplier;
4231             vel[2] = (viewer.z - oldviewer.z) / multiplier;
4232
4233             //Set orientation with forward and up vectors
4234             static XYZ upvector;
4235             upvector = 0;
4236             upvector.z = -1;
4237
4238             upvector = DoRotation(upvector, -pitch + 90, 0, 0);
4239             upvector = DoRotation(upvector, 0, 0 - yaw, 0);
4240
4241             facing = 0;
4242             facing.z = -1;
4243
4244             facing = DoRotation(facing, -pitch, 0, 0);
4245             facing = DoRotation(facing, 0, 0 - yaw, 0);
4246
4247
4248             static float ori[6];
4249             ori[0] = -facing.x;
4250             ori[1] = facing.y;
4251             ori[2] = -facing.z;
4252             ori[3] = -upvector.x;
4253             ori[4] = upvector.y;
4254             ori[5] = -upvector.z;
4255
4256             OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
4257             OPENAL_Update();
4258
4259             oldviewer = viewer;
4260         }
4261     }
4262
4263     if (Input::isKeyPressed(SDL_SCANCODE_F1))
4264         Screenshot();
4265 }
4266
4267 void Game::TickOnce()
4268 {
4269     if (mainmenu) {
4270         yaw += multiplier * 5;
4271     } else if (Dialog::directing || !Dialog::inDialog()) {
4272         yaw += deltah * .7;
4273         if (invertmouse) {
4274             pitch -= deltav * .7;
4275         } else {
4276             pitch += deltav * .7;
4277         }
4278         if (pitch > 90)
4279             pitch = 90;
4280         if (pitch < -70)
4281             pitch = -70;
4282     }
4283 }
4284
4285 void Game::TickOnceAfter()
4286 {
4287     static XYZ colviewer;
4288     static XYZ coltarget;
4289     static XYZ target;
4290     static XYZ col;
4291     static XYZ facing;
4292     static float changedelay;
4293     static bool alldead;
4294     static float unseendelay;
4295     static float cameraspeed;
4296
4297     if (!mainmenu) {
4298         static int oldmusictype = musictype;
4299
4300         if (environment == snowyenvironment)
4301             leveltheme = stream_snowtheme;
4302         if (environment == grassyenvironment)
4303             leveltheme = stream_grasstheme;
4304         if (environment == desertenvironment)
4305             leveltheme = stream_deserttheme;
4306
4307         realthreat = 0;
4308
4309         musictype = leveltheme;
4310         for (unsigned i = 0; i < Person::players.size(); i++) {
4311             if ((Person::players[i]->aitype == attacktypecutoff ||
4312                     Person::players[i]->aitype == getweapontype ||
4313                     Person::players[i]->aitype == gethelptype ||
4314                     Person::players[i]->aitype == searchtype) &&
4315                     !Person::players[i]->dead/*&&Person::players[i]->surprised<=0*/ &&
4316                     (Person::players[i]->animTarget != sneakattackedanim &&
4317                      Person::players[i]->animTarget != knifesneakattackedanim &&
4318                      Person::players[i]->animTarget != swordsneakattackedanim)) {
4319                 musictype = stream_fighttheme;
4320                 realthreat = 1;
4321             }
4322         }
4323         if (Person::players[0]->dead)
4324             musictype = stream_menutheme;
4325
4326
4327         if (musictype == stream_fighttheme)
4328             unseendelay = 1;
4329
4330         if (oldmusictype == stream_fighttheme && musictype != stream_fighttheme) {
4331             unseendelay -= multiplier;
4332             if (unseendelay > 0)
4333                 musictype = stream_fighttheme;
4334         }
4335
4336
4337         if (loading == 2) {
4338             musictype = stream_menutheme;
4339             musicvolume[2] = 512;
4340             musicvolume[0] = 0;
4341             musicvolume[1] = 0;
4342             musicvolume[3] = 0;
4343         }
4344
4345         if (musictoggle)
4346             if (musictype != oldmusictype && musictype == stream_fighttheme)
4347                 emit_sound_np(alarmsound);
4348         musicselected = musictype;
4349
4350         if (musicselected == leveltheme)
4351             musicvolume[0] += multiplier * 450;
4352         else
4353             musicvolume[0] -= multiplier * 450;
4354         if (musicselected == stream_fighttheme)
4355             musicvolume[1] += multiplier * 450;
4356         else
4357             musicvolume[1] -= multiplier * 450;
4358         if (musicselected == stream_menutheme)
4359             musicvolume[2] += multiplier * 450;
4360         else
4361             musicvolume[2] -= multiplier * 450;
4362
4363         for (int i = 0; i < 3; i++) {
4364             if (musicvolume[i] < 0)
4365                 musicvolume[i] = 0;
4366             if (musicvolume[i] > 512)
4367                 musicvolume[i] = 512;
4368         }
4369
4370         if (musicvolume[2] > 128 && !loading && !mainmenu)
4371             musicvolume[2] = 128;
4372
4373         if (musictoggle) {
4374             if (musicvolume[0] > 0 && oldmusicvolume[0] <= 0)
4375                 emit_stream_np(leveltheme, musicvolume[0]);
4376             if (musicvolume[1] > 0 && oldmusicvolume[1] <= 0)
4377                 emit_stream_np(stream_fighttheme, musicvolume[1]);
4378             if (musicvolume[2] > 0 && oldmusicvolume[2] <= 0)
4379                 emit_stream_np(stream_menutheme, musicvolume[2]);
4380             if (musicvolume[0] <= 0 && oldmusicvolume[0] > 0)
4381                 pause_sound(leveltheme);
4382             if (musicvolume[1] <= 0 && oldmusicvolume[1] > 0)
4383                 pause_sound(stream_fighttheme);
4384             if (musicvolume[2] <= 0 && oldmusicvolume[2] > 0)
4385                 pause_sound(stream_menutheme);
4386
4387             if (musicvolume[0] != oldmusicvolume[0])
4388                 OPENAL_SetVolume(channels[leveltheme], musicvolume[0]);
4389             if (musicvolume[1] != oldmusicvolume[1])
4390                 OPENAL_SetVolume(channels[stream_fighttheme], musicvolume[1]);
4391             if (musicvolume[2] != oldmusicvolume[2])
4392                 OPENAL_SetVolume(channels[stream_menutheme], musicvolume[2]);
4393
4394             for (int i = 0; i < 3; i++)
4395                 oldmusicvolume[i] = musicvolume[i];
4396         } else {
4397             pause_sound(leveltheme);
4398             pause_sound(stream_fighttheme);
4399             pause_sound(stream_menutheme);
4400
4401             for (int i = 0; i < 4; i++) {
4402                 oldmusicvolume[i] = 0;
4403                 musicvolume[i] = 0;
4404             }
4405         }
4406
4407         Hotspot::killhotspot = 2;
4408         for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
4409             if (Hotspot::hotspots[i].type > 10 && Hotspot::hotspots[i].type < 20) {
4410                 if (Person::players[Hotspot::hotspots[i].type - 10]->dead == 0)
4411                     Hotspot::killhotspot = 0;
4412                 else if (Hotspot::killhotspot == 2)
4413                     Hotspot::killhotspot = 1;
4414             }
4415         }
4416         if (Hotspot::killhotspot == 2)
4417             Hotspot::killhotspot = 0;
4418
4419
4420         winhotspot = false;
4421         for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
4422             if (Hotspot::hotspots[i].type == -1) {
4423                 if (distsq(&Person::players[0]->coords, &Hotspot::hotspots[i].position) < Hotspot::hotspots[i].size) {
4424                     winhotspot = true;
4425                 }
4426             }
4427         }
4428
4429         int numalarmed = 0;
4430         for (unsigned i = 1; i < Person::players.size(); i++) {
4431             if (!Person::players[i]->dead && Person::players[i]->aitype == attacktypecutoff && Person::players[i]->surprised <= 0) {
4432                 numalarmed++;
4433             }
4434         }
4435         if (numalarmed > maxalarmed) {
4436             maxalarmed = numalarmed;
4437         }
4438
4439         if (changedelay <= 0 && !loading && !editorenabled && gameon && !Tutorial::active && changedelay != -999 && !won) {
4440             if (Person::players[0]->dead && changedelay <= 0) {
4441                 changedelay = 1;
4442                 targetlevel = whichlevel;
4443             }
4444             alldead = true;
4445             for (unsigned i = 1; i < Person::players.size(); i++) {
4446                 if (!Person::players[i]->dead && Person::players[i]->howactive < typedead1) {
4447                     alldead = false;
4448                     break;
4449                 }
4450             }
4451
4452
4453             if (alldead && !Person::players[0]->dead && maptype == mapkilleveryone) {
4454                 changedelay = 1;
4455                 targetlevel = whichlevel + 1;
4456                 if (targetlevel > numchallengelevels - 1)
4457                     targetlevel = 0;
4458             }
4459             if (winhotspot || windialogue) {
4460                 changedelay = 0.1;
4461                 targetlevel = whichlevel + 1;
4462                 if (targetlevel > numchallengelevels - 1)
4463                     targetlevel = 0;
4464             }
4465
4466
4467             if (Hotspot::killhotspot) {
4468                 changedelay = 1;
4469                 targetlevel = whichlevel + 1;
4470                 if (targetlevel > numchallengelevels - 1)
4471                     targetlevel = 0;
4472             }
4473
4474             if (changedelay > 0 && !Person::players[0]->dead && !won) {
4475                 //high scores, awards, win
4476                 if (campaign) {
4477                     Account::active().winCampaignLevel(whichchoice, bonustotal, leveltime);
4478                     scoreadded = 1;
4479                 } else {
4480                     wonleveltime = leveltime;
4481                     Account::active().winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
4482                 }
4483                 won = 1;
4484                 Account::saveFile(Folders::getUserSavePath());
4485             }
4486         }
4487
4488         if (!winfreeze) {
4489
4490             if (leveltime < 1) {
4491                 loading = 0;
4492                 changedelay = .1;
4493                 alldead = false;
4494                 winhotspot = false;
4495                 Hotspot::killhotspot = 0;
4496             }
4497
4498             if (!editorenabled && gameon && !mainmenu) {
4499                 if (changedelay != -999)
4500                     changedelay -= multiplier / 7;
4501                 if (Person::players[0]->dead)
4502                     targetlevel = whichlevel;
4503                 if (loading == 2 && !campaign) {
4504                     flash();
4505
4506                     fireSound(firestartsound);
4507
4508                     if (!Person::players[0]->dead && targetlevel != whichlevel)
4509                         startbonustotal = bonustotal;
4510                     if (Person::players[0]->dead)
4511                         Loadlevel(whichlevel);
4512                     else
4513                         Loadlevel(targetlevel);
4514
4515                     fireSound();
4516
4517                     loading = 3;
4518                 }
4519                 if (loading == 2 && targetlevel == whichlevel) {
4520                     flash();
4521                     loadtime = 0;
4522
4523                     fireSound(firestartsound);
4524
4525                     Loadlevel(campaignlevels[Account::active().getCampaignChoicesMade()].mapname.c_str());
4526
4527                     fireSound();
4528
4529                     loading = 3;
4530                 }
4531                 if (changedelay <= -999 &&
4532                         whichlevel != -2 &&
4533                         !loading &&
4534                         (Person::players[0]->dead ||
4535                          (alldead && maptype == mapkilleveryone) ||
4536                          (winhotspot) ||
4537                          (Hotspot::killhotspot)))
4538                     loading = 1;
4539                 if ((Person::players[0]->dead ||
4540                         (alldead && maptype == mapkilleveryone) ||
4541                         (winhotspot) ||
4542                         (windialogue) ||
4543                         (Hotspot::killhotspot)) &&
4544                         changedelay <= 0) {
4545                     if (whichlevel != -2 && !loading && !Person::players[0]->dead) {
4546                         winfreeze = true;
4547                         changedelay = -999;
4548                     }
4549                     if (Person::players[0]->dead)
4550                         loading = 1;
4551                 }
4552             }
4553
4554             if (campaign) {
4555                 // campaignchoosenext determines what to do when the level is complete:
4556                 // 0 = load next level
4557                 // 1 = go back to level select screen
4558                 // 2 = stealthload next level
4559                 if (mainmenu == 0 && winfreeze && (campaignlevels[actuallevel].choosenext) == 1) {
4560                     if (campaignlevels[actuallevel].nextlevel.empty())
4561                         endgame = 1;
4562                 } else if (mainmenu == 0 && winfreeze) {
4563                     stealthloading = (campaignlevels[actuallevel].choosenext == 2);
4564
4565                     if (!stealthloading) {
4566                         fireSound(firestartsound);
4567
4568                         flash();
4569                     }
4570
4571                     startbonustotal = 0;
4572
4573                     LoadCampaign();
4574
4575                     loading = 2;
4576                     loadtime = 0;
4577                     targetlevel = 7;
4578                     if (!firstload)
4579                         LoadStuff();
4580                     whichchoice = 0;
4581                     actuallevel = campaignlevels[actuallevel].nextlevel.front();
4582                     visibleloading = true;
4583                     stillloading = 1;
4584                     Loadlevel(campaignlevels[actuallevel].mapname.c_str());
4585                     campaign = 1;
4586                     mainmenu = 0;
4587                     gameon = 1;
4588                     pause_sound(stream_menutheme);
4589
4590                     stealthloading = 0;
4591                 }
4592             }
4593
4594             if (loading == 3)
4595                 loading = 0;
4596
4597         }
4598
4599         oldmusictype = musictype;
4600     }
4601
4602     facing = 0;
4603     facing.z = -1;
4604
4605     facing = DoRotation(facing, -pitch, 0, 0);
4606     facing = DoRotation(facing, 0, 0 - yaw, 0);
4607     viewerfacing = facing;
4608
4609     if (!cameramode) {
4610         if ((Animation::animations[Person::players[0]->animTarget].attack != 3 && Animation::animations[Person::players[0]->animCurrent].attack != 3) || Person::players[0]->skeleton.free)
4611             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;
4612         else
4613             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;
4614         target.y += .1;
4615         if (Person::players[0]->skeleton.free) {
4616             for (unsigned i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
4617                 if (Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y > target.y)
4618                     target.y = Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y;
4619             }
4620             target.y += .1;
4621         }
4622         if (Person::players[0]->skeleton.free != 2) {
4623             cameraspeed = 20;
4624             if (findLengthfast(&Person::players[0]->velocity) > 400) {
4625                 cameraspeed = 20 + (findLength(&Person::players[0]->velocity) - 20) * .96;
4626             }
4627             if (Person::players[0]->skeleton.free == 0 && Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim)
4628                 target.y += 1.4;
4629             coltarget = target - cameraloc;
4630             if (findLengthfast(&coltarget) < multiplier * multiplier * 400)
4631                 cameraloc = target;
4632             else {
4633                 Normalise(&coltarget);
4634                 if (Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim && Person::players[0]->animCurrent != climbanim && Person::players[0]->currentoffset.x == 0)
4635                     cameraloc = cameraloc + coltarget * multiplier * cameraspeed;
4636                 else
4637                     cameraloc = cameraloc + coltarget * multiplier * 8;
4638             }
4639             if (editorenabled)
4640                 cameraloc = target;
4641             cameradist += multiplier * 5;
4642             if (cameradist > 2.3)
4643                 cameradist = 2.3;
4644             viewer = cameraloc - facing * cameradist;
4645             colviewer = viewer;
4646             coltarget = cameraloc;
4647             Object::SphereCheckPossible(&colviewer, findDistance(&colviewer, &coltarget));
4648             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
4649                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
4650                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
4651                     colviewer = viewer;
4652                     coltarget = cameraloc;
4653                     if (Object::objects[i]->model.LineCheckPossible(&colviewer, &coltarget, &col, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
4654                         viewer = col;
4655                 }
4656             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
4657                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
4658                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
4659                     colviewer = viewer;
4660                     if (Object::objects[i]->model.SphereCheck(&colviewer, .15, &col, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
4661                         viewer = colviewer;
4662                     }
4663                 }
4664             cameradist = findDistance(&viewer, &target);
4665             viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .6);
4666             if (cameraloc.y < terrain.getHeight(cameraloc.x, cameraloc.z)) {
4667                 cameraloc.y = terrain.getHeight(cameraloc.x, cameraloc.z);
4668             }
4669         }
4670         if (camerashake > .8)
4671             camerashake = .8;
4672         woozy += multiplier;
4673         if (Person::players[0]->dead)
4674             camerashake = 0;
4675         if (Person::players[0]->dead)
4676             woozy = 0;
4677         camerashake -= multiplier * 2;
4678         blackout -= multiplier * 2;
4679         if (camerashake < 0)
4680             camerashake = 0;
4681         if (blackout < 0)
4682             blackout = 0;
4683         if (camerashake) {
4684             viewer.x += (float)(Random() % 100) * .0005 * camerashake;
4685             viewer.y += (float)(Random() % 100) * .0005 * camerashake;
4686             viewer.z += (float)(Random() % 100) * .0005 * camerashake;
4687         }
4688     }
4689 }
4690