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